mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'master' into js/improve-getAResponseDataNode
This commit is contained in:
@@ -36,5 +36,6 @@ The following changes in version 1.23 affect C# analysis in all applications.
|
||||
picture of the partial flow paths from a given source. The feature is
|
||||
disabled by default and can be enabled for individual configurations by
|
||||
overriding `int explorationLimit()`.
|
||||
* `foreach` statements where the body is guaranteed to be executed at least once, such as `foreach (var x in new string[]{ "a", "b", "c" }) { ... }`, are now recognized by all analyses based on the control flow graph (such as SSA, data flow and taint tracking).
|
||||
|
||||
## Changes to autobuilder
|
||||
|
||||
@@ -13,16 +13,20 @@
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|---------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Unused index variable (`js/unused-index-variable`) | correctness | Highlights loops that iterate over an array, but do not use the index variable to access array elements, indicating a possible typo or logic error. |
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
|
||||
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. |
|
||||
| Client-side cross-site scripting (`js/xss`) | More results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized. |
|
||||
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. |
|
||||
| Hard-coded credentials (`js/hardcoded-credentials`) | Fewer false-positive results | This rule now flags fewer password examples. |
|
||||
| Incorrect suffix check (`js/incorrect-suffix-check`) | Fewer false-positive results | The query recognizes valid checks in more cases.
|
||||
| Network data written to file (`js/http-to-file-access`) | Fewer false-positive results | This query has been renamed to better match its intended purpose, and now only considers network data untrusted. |
|
||||
| Password in configuration file (`js/password-in-configuration-file`) | Fewer false-positive results | This rule now flags fewer password examples. |
|
||||
| Prototype pollution (`js/prototype-pollution`) | More results | The query now highlights vulnerable uses of jQuery and Angular, and the results are shown on LGTM by default. |
|
||||
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now treats responses from servers as untrusted. |
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
"TaintTracking::Configuration Java/C++/C#": [
|
||||
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||
|
||||
@@ -4,7 +4,21 @@ import semmle.code.cpp.Initializer
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
/**
|
||||
* A C/C++ variable.
|
||||
* A C/C++ variable. For example, in the following code there are four
|
||||
* variables, `a`, `b`, `c` and `d`:
|
||||
* ```
|
||||
* extern int a;
|
||||
* int a;
|
||||
*
|
||||
* void myFunction(int b) {
|
||||
* int c;
|
||||
* }
|
||||
*
|
||||
* namespace N {
|
||||
* extern int d;
|
||||
* int d = 1;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* For local variables, there is a one-to-one correspondence between
|
||||
* `Variable` and `VariableDeclarationEntry`.
|
||||
@@ -162,7 +176,22 @@ class Variable extends Declaration, @variable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A particular declaration or definition of a C/C++ variable.
|
||||
* A particular declaration or definition of a C/C++ variable. For example, in
|
||||
* the following code there are six variable declaration entries - two each for
|
||||
* `a` and `d`, and one each for `b` and `c`:
|
||||
* ```
|
||||
* extern int a;
|
||||
* int a;
|
||||
*
|
||||
* void myFunction(int b) {
|
||||
* int c;
|
||||
* }
|
||||
*
|
||||
* namespace N {
|
||||
* extern int d;
|
||||
* int d = 1;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
override Variable getDeclaration() { result = getVariable() }
|
||||
@@ -183,13 +212,13 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
* because the parameter may have a different name in the declaration
|
||||
* than in the definition. For example:
|
||||
*
|
||||
* ```
|
||||
* // Declaration. Parameter is named "x".
|
||||
* int f(int x);
|
||||
* ```
|
||||
* // Declaration. Parameter is named "x".
|
||||
* int f(int x);
|
||||
*
|
||||
* // Definition. Parameter is named "y".
|
||||
* int f(int y) { return y; }
|
||||
* ```
|
||||
* // Definition. Parameter is named "y".
|
||||
* int f(int y) { return y; }
|
||||
* ```
|
||||
*/
|
||||
override string getName() { var_decls(underlyingElement(this), _, _, result, _) and result != "" }
|
||||
|
||||
@@ -215,7 +244,13 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
|
||||
/**
|
||||
* A parameter as described within a particular declaration or definition
|
||||
* of a C/C++ function.
|
||||
* of a C/C++ function. For example the declaration of `a` in the following
|
||||
* code:
|
||||
* ```
|
||||
* void myFunction(int a) {
|
||||
* int b;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
ParameterDeclarationEntry() { param_decl_bind(underlyingElement(this), _, _) }
|
||||
@@ -272,8 +307,17 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
|
||||
/**
|
||||
* A C/C++ variable with block scope [N4140 3.3.3]. In other words, a local
|
||||
* variable or a function parameter. Local variables can be static; use the
|
||||
* `isStatic` member predicate to detect those.
|
||||
* variable or a function parameter. For example, the variables `a`, `b` and
|
||||
* `c` in the following code:
|
||||
* ```
|
||||
* void myFunction(int a) {
|
||||
* int b;
|
||||
* static int c;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Local variables can be static; use the `isStatic` member predicate to
|
||||
* detect those.
|
||||
*/
|
||||
class LocalScopeVariable extends Variable, @localscopevariable {
|
||||
/** Gets the function to which this variable belongs. */
|
||||
@@ -292,6 +336,14 @@ deprecated class StackVariable extends Variable {
|
||||
/**
|
||||
* A C/C++ local variable. In other words, any variable that has block
|
||||
* scope [N4140 3.3.3], but is not a parameter of a `Function` or `CatchBlock`.
|
||||
* For example the variables `b` and `c` in the following code:
|
||||
* ```
|
||||
* void myFunction(int a) {
|
||||
* int b;
|
||||
* static int c;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Local variables can be static; use the `isStatic` member predicate to detect
|
||||
* those.
|
||||
*
|
||||
@@ -310,7 +362,15 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ variable which has global scope or namespace scope.
|
||||
* A C/C++ variable which has global scope or namespace scope. For example the
|
||||
* variables `a` and `b` in the following code:
|
||||
* ```
|
||||
* int a;
|
||||
*
|
||||
* namespace N {
|
||||
* int b;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class GlobalOrNamespaceVariable extends Variable, @globalvariable {
|
||||
override string getName() { globalvariables(underlyingElement(this), _, result) }
|
||||
@@ -321,7 +381,15 @@ class GlobalOrNamespaceVariable extends Variable, @globalvariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ variable which has namespace scope.
|
||||
* A C/C++ variable which has namespace scope. For example the variable `b`
|
||||
* in the following code:
|
||||
* ```
|
||||
* int a;
|
||||
*
|
||||
* namespace N {
|
||||
* int b;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class NamespaceVariable extends GlobalOrNamespaceVariable {
|
||||
NamespaceVariable() {
|
||||
@@ -330,7 +398,15 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ variable which has global scope.
|
||||
* A C/C++ variable which has global scope. For example the variable `a`
|
||||
* in the following code:
|
||||
* ```
|
||||
* int a;
|
||||
*
|
||||
* namespace N {
|
||||
* int b;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Note that variables declared in anonymous namespaces have namespace scope,
|
||||
* even though they are accessed in the same manner as variables declared in
|
||||
@@ -341,7 +417,15 @@ class GlobalVariable extends GlobalOrNamespaceVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A C structure member or C++ member variable.
|
||||
* A C structure member or C++ member variable. For example the member
|
||||
* variables `m` and `s` in the following code:
|
||||
* ```
|
||||
* class MyClass {
|
||||
* public:
|
||||
* int m;
|
||||
* static int s;
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* This includes static member variables in C++. To exclude static member
|
||||
* variables, use `Field` instead of `MemberVariable`.
|
||||
@@ -395,7 +479,12 @@ deprecated class FunctionPointerMemberVariable extends MemberVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++14 variable template.
|
||||
* A C++14 variable template. For example, in the following code the variable
|
||||
* template `v` defines a family of variables:
|
||||
* ```
|
||||
* template<class T>
|
||||
* T v;
|
||||
* ```
|
||||
*/
|
||||
class TemplateVariable extends Variable {
|
||||
TemplateVariable() { is_variable_template(underlyingElement(this)) }
|
||||
@@ -410,7 +499,24 @@ class TemplateVariable extends Variable {
|
||||
* A non-static local variable or parameter that is not part of an
|
||||
* uninstantiated template. Uninstantiated templates are purely syntax, and
|
||||
* only on instantiation will they be complete with information about types,
|
||||
* conversions, call targets, etc.
|
||||
* conversions, call targets, etc. For example in the following code, the
|
||||
* variables `a` in `myFunction` and `b` in the instantiation
|
||||
* `myTemplateFunction<int>`, but not `b` in the template
|
||||
* `myTemplateFunction<T>`:
|
||||
* ```
|
||||
* void myFunction() {
|
||||
* T a;
|
||||
* }
|
||||
*
|
||||
* template<type T>
|
||||
* void myTemplateFunction() {
|
||||
* T b;
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* myTemplateFunction<int>();
|
||||
* ```
|
||||
*/
|
||||
class SemanticStackVariable extends LocalScopeVariable {
|
||||
SemanticStackVariable() {
|
||||
|
||||
@@ -166,3 +166,17 @@ class MicrosoftInt64Type extends IntegralType {
|
||||
not isExplicitlySigned()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__builtin_va_list` type, used to provide variadic functionality.
|
||||
*
|
||||
* This is a complement to the `__builtin_va_start`, `__builtin_va_end`,
|
||||
* `__builtin_va_copy` and `__builtin_va_arg` expressions.
|
||||
*/
|
||||
class BuiltInVarArgsList extends Type {
|
||||
BuiltInVarArgsList() {
|
||||
this.hasName("__builtin_va_list")
|
||||
}
|
||||
|
||||
override string getCanonicalQLClass() { result = "BuiltInVarArgsList" }
|
||||
}
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -226,6 +226,29 @@ class ImplicitThisFieldAccess extends FieldAccess {
|
||||
ImplicitThisFieldAccess() { not exists(this.getQualifier()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ _pointer to non-static data member_ literal. For example, `&C::x` is
|
||||
* an expression that refers to field `x` of class `C`. If the type of that
|
||||
* field is `int`, then `&C::x` ought to have type `int C::*`. It is currently
|
||||
* modeled in QL as having type `int`.
|
||||
*
|
||||
* See [dcl.mptr] in the C++17 standard or see
|
||||
* https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members.
|
||||
*/
|
||||
class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
PointerToFieldLiteral() {
|
||||
// The extractor currently emits a pointer-to-field literal as a field
|
||||
// access without a qualifier. The only other unqualified field accesses it
|
||||
// emits are for compiler-generated constructors and destructors. When we
|
||||
// filter those out, there are only pointer-to-field literals left.
|
||||
not this.isCompilerGenerated()
|
||||
}
|
||||
|
||||
override predicate isConstant() { any() }
|
||||
|
||||
override string getCanonicalQLClass() { result = "PointerToFieldLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ function access expression.
|
||||
*/
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
*
|
||||
* 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`.
|
||||
* (intraprocedural) data flow between expressions, call
|
||||
* `DataFlow::localExprFlow`. For more general cases of local data flow, call
|
||||
* `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type
|
||||
* `DataFlow::Node`.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
|
||||
* `DataFlow4::Configuration`.
|
||||
*
|
||||
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
|
||||
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
|
||||
* `DataFlow4::Configuration`.
|
||||
*
|
||||
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
|
||||
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
|
||||
* `DataFlow4::Configuration`.
|
||||
*
|
||||
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
|
||||
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
159
cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll
Normal file
159
cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll
Normal file
@@ -0,0 +1,159 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Security
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
/**
|
||||
* A predictable expression is one where an external user can predict
|
||||
* the value. For example, a literal in the source code is considered
|
||||
* predictable.
|
||||
*/
|
||||
// TODO: Change to use Instruction instead of Expr. Naive attempt breaks
|
||||
// TaintedAllocationSize qltest.
|
||||
private predicate predictable(Expr expr) {
|
||||
expr instanceof Literal
|
||||
or
|
||||
exists(BinaryOperation binop | binop = expr |
|
||||
predictable(binop.getLeftOperand()) and predictable(binop.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(UnaryOperation unop | unop = expr | predictable(unop.getOperand()))
|
||||
}
|
||||
|
||||
// TODO: remove when `predictable` has an `Instruction` parameter instead of `Expr`.
|
||||
private predicate predictableInstruction(Instruction instr) {
|
||||
predictable(DataFlow::instructionNode(instr).asExpr())
|
||||
}
|
||||
|
||||
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
|
||||
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { any() }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
instructionTaintStep(n1.asInstruction(), n2.asInstruction())
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) {
|
||||
exists(Variable checkedVar |
|
||||
accessesVariable(node.asInstruction(), checkedVar) and
|
||||
hasUpperBoundsCheck(checkedVar)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate accessesVariable(CopyInstruction copy, Variable var) {
|
||||
exists(VariableAddressInstruction va | va.getVariable().getAST() = var |
|
||||
copy.(StoreInstruction).getDestinationAddress() = va
|
||||
or
|
||||
copy.(LoadInstruction).getSourceAddress() = va
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable that has any kind of upper-bound check anywhere in the program
|
||||
*/
|
||||
// TODO: This coarse overapproximation, ported from the old taint tracking
|
||||
// library, could be replaced with an actual semantic check that a particular
|
||||
// variable _access_ is guarded by an upper-bound check. We probably don't want
|
||||
// to do this right away since it could expose a lot of FPs that were
|
||||
// previously suppressed by this predicate by coincidence.
|
||||
private predicate hasUpperBoundsCheck(Variable var) {
|
||||
exists(RelationalOperation oper, VariableAccess access |
|
||||
oper.getLeftOperand() = access and
|
||||
access.getTarget() = var and
|
||||
// Comparing to 0 is not an upper bound check
|
||||
not oper.getRightOperand().getValue() = "0"
|
||||
)
|
||||
}
|
||||
|
||||
private predicate instructionTaintStep(Instruction i1, Instruction i2) {
|
||||
// Expressions computed from tainted data are also tainted
|
||||
i2 = any(CallInstruction call |
|
||||
isPureFunction(call.getStaticCallTarget().getName()) and
|
||||
call.getAnArgument() = i1 and
|
||||
forall(Instruction arg | arg = call.getAnArgument() | arg = i1 or predictableInstruction(arg)) and
|
||||
// flow through `strlen` tends to cause dubious results, if the length is
|
||||
// bounded.
|
||||
not call.getStaticCallTarget().getName() = "strlen"
|
||||
)
|
||||
or
|
||||
// Flow through pointer dereference
|
||||
i2.(LoadInstruction).getSourceAddress() = i1
|
||||
or
|
||||
i2.(UnaryInstruction).getUnary() = i1
|
||||
or
|
||||
exists(BinaryInstruction bin |
|
||||
bin = i2 and
|
||||
predictableInstruction(i2.getAnOperand().getDef()) and
|
||||
i1 = i2.getAnOperand().getDef()
|
||||
)
|
||||
// TODO: Check that we have flow from `a` to `a[i]`. It may work for constant
|
||||
// `i` because there is flow through `predictable` `BinaryInstruction` and
|
||||
// through `LoadInstruction`.
|
||||
//
|
||||
// TODO: Flow from argument to return of known functions: Port missing parts
|
||||
// of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
|
||||
// libraries.
|
||||
//
|
||||
// TODO: Flow from input argument to output argument of known functions: Port
|
||||
// missing parts of `copyValueBetweenArguments` to the `interfaces.Taint` and
|
||||
// `interfaces.DataFlow` libraries and implement call side-effect nodes. This
|
||||
// will help with the test for `ExecTainted.ql`. The test for
|
||||
// `TaintedPath.ql` is more tricky because the output arg is a pointer
|
||||
// addition expression.
|
||||
}
|
||||
|
||||
predicate tainted(Expr source, Element tainted) {
|
||||
exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink |
|
||||
cfg.hasFlow(DataFlow::exprNode(source), sink)
|
||||
|
|
||||
// TODO: is it more appropriate to use asConvertedExpr here and avoid
|
||||
// `getConversion*`? Or will that cause us to miss some cases where there's
|
||||
// flow to a conversion (like a `ReferenceDereferenceExpr`) and we want to
|
||||
// pretend there was flow to the converted `Expr` for the sake of
|
||||
// compatibility.
|
||||
sink.asExpr().getConversion*() = tainted
|
||||
or
|
||||
// For compatibility, send flow from arguments to parameters, even for
|
||||
// functions with no body.
|
||||
exists(FunctionCall call, int i |
|
||||
sink.asExpr() = call.getArgument(i) and
|
||||
tainted = resolveCall(call).getParameter(i)
|
||||
)
|
||||
or
|
||||
// For compatibility, send flow into a `Variable` if there is flow to any
|
||||
// Load or Store of that variable.
|
||||
exists(CopyInstruction copy |
|
||||
copy.getSourceValue() = sink.asInstruction() and
|
||||
accessesVariable(copy, tainted) and
|
||||
not hasUpperBoundsCheck(tainted)
|
||||
)
|
||||
or
|
||||
// For compatibility, send flow into a `NotExpr` even if it's part of a
|
||||
// short-circuiting condition and thus might get skipped.
|
||||
tainted.(NotExpr).getOperand() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
predicate taintedIncludingGlobalVars(Expr source, Element tainted, string globalVar) {
|
||||
tainted(source, tainted) and
|
||||
// TODO: Find a way to emulate how `security.TaintTracking` reports the last
|
||||
// global variable that taint has passed through. Also make sure we emulate
|
||||
// its behavior for interprocedural flow through globals.
|
||||
globalVar = ""
|
||||
}
|
||||
|
||||
GlobalOrNamespaceVariable globalVarFromId(string id) {
|
||||
// TODO: Implement this when `taintedIncludingGlobalVars` has support for
|
||||
// global variables.
|
||||
none()
|
||||
}
|
||||
|
||||
Function resolveCall(Call call) {
|
||||
// TODO: improve virtual dispatch. This will help in the test for
|
||||
// `UncontrolledProcessOperation.ql`.
|
||||
result = call.getTarget()
|
||||
}
|
||||
@@ -6,166 +6,24 @@
|
||||
* the information from the source is preserved at the sink. For example, taint
|
||||
* propagates from `x` to `x + 100`, but it does not propagate from `x` to `x >
|
||||
* 100` since we consider a single bit of information to be too little.
|
||||
*
|
||||
* To use global (interprocedural) taint tracking, extend the class
|
||||
* `TaintTracking::Configuration` as documented on that class. To use local
|
||||
* (intraprocedural) taint tracking between expressions, call
|
||||
* `TaintTracking::localExprTaint`. For more general cases of local taint
|
||||
* tracking, call `TaintTracking::localTaint` or
|
||||
* `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow2
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
module TaintTracking {
|
||||
/**
|
||||
* A configuration of interprocedural taint tracking analysis. This defines
|
||||
* sources, sinks, and any other configurable aspect of the analysis. Each
|
||||
* use of the taint tracking library must define its own unique extension of
|
||||
* this abstract class.
|
||||
*
|
||||
* A taint-tracking configuration is a special data flow configuration
|
||||
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
|
||||
* necessarily preserve values but are still relevant from a taint-tracking
|
||||
* perspective. (For example, string concatenation, where one of the operands
|
||||
* is tainted.)
|
||||
*
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
* // Optionally override `isSanitizer`.
|
||||
* // Optionally override `isAdditionalTaintStep`.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
* Multiple configurations can coexist, but it is unsupported to depend on a
|
||||
* `TaintTracking::Configuration` or a `DataFlow::Configuration` in the
|
||||
* overridden predicates that define sources, sinks, or additional steps.
|
||||
* Instead, the dependency should go to a `TaintTracking::Configuration2` or
|
||||
* a `DataFlow{2,3,4}::Configuration`.
|
||||
*/
|
||||
abstract class Configuration extends DataFlow::Configuration {
|
||||
bindingset[this]
|
||||
Configuration() { any() }
|
||||
|
||||
/** Holds if `source` is a taint source. */
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
|
||||
/** Holds if `sink` is a taint sink. */
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
|
||||
/**
|
||||
* Holds if taint should not flow into `node`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step
|
||||
* from `source` to `target` must be taken into account in the analysis.
|
||||
* This step will only be followed if `target` is not in the `isSanitizer`
|
||||
* predicate.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(DataFlow::Node source, DataFlow::Node target) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node target) {
|
||||
this.isAdditionalTaintStep(source, target)
|
||||
or
|
||||
localTaintStep(source, target)
|
||||
}
|
||||
}
|
||||
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
|
||||
private import semmle.code.cpp.ir.dataflow.TaintTracking2
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration that is backed by the `DataFlow2` library
|
||||
* instead of `DataFlow`. Use this class when taint-tracking configurations
|
||||
* or data-flow configurations must depend on each other.
|
||||
*
|
||||
* See `TaintTracking::Configuration` for the full documentation.
|
||||
* DEPRECATED: Use TaintTracking2::Configuration instead.
|
||||
*/
|
||||
abstract class Configuration2 extends DataFlow2::Configuration {
|
||||
bindingset[this]
|
||||
Configuration2() { any() }
|
||||
|
||||
/** Holds if `source` is a taint source. */
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
|
||||
/** Holds if `sink` is a taint sink. */
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
|
||||
/**
|
||||
* Holds if taint should not flow into `node`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step
|
||||
* from `source` to `target` must be taken into account in the analysis.
|
||||
* This step will only be followed if `target` is not in the `isSanitizer`
|
||||
* predicate.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(DataFlow::Node source, DataFlow::Node target) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node target) {
|
||||
this.isAdditionalTaintStep(source, target)
|
||||
or
|
||||
localTaintStep(source, target)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step.
|
||||
*/
|
||||
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
// Taint can flow into using ordinary data flow.
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
localInstructionTaintStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step.
|
||||
*/
|
||||
private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction nodeTo) {
|
||||
// Taint can flow through expressions that alter the value but preserve
|
||||
// more than one bit of it _or_ expressions that follow data through
|
||||
// pointer indirections.
|
||||
nodeTo.getAnOperand().getAnyDef() = nodeFrom and
|
||||
(
|
||||
nodeTo instanceof ArithmeticInstruction
|
||||
or
|
||||
nodeTo instanceof BitwiseInstruction
|
||||
or
|
||||
nodeTo instanceof PointerArithmeticInstruction
|
||||
or
|
||||
nodeTo instanceof FieldAddressInstruction
|
||||
or
|
||||
// The `CopyInstruction` case is also present in non-taint data flow, but
|
||||
// that uses `getDef` rather than `getAnyDef`. For taint, we want flow
|
||||
// from a definition of `myStruct` to a `myStruct.myField` expression.
|
||||
nodeTo instanceof CopyInstruction
|
||||
)
|
||||
or
|
||||
nodeTo.(LoadInstruction).getSourceAddress() = nodeFrom
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `source` to `sink` in zero or more local
|
||||
* (intra-procedural) steps.
|
||||
*/
|
||||
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
|
||||
deprecated class Configuration2 = TaintTracking2::Configuration;
|
||||
}
|
||||
|
||||
15
cpp/ql/src/semmle/code/cpp/ir/dataflow/TaintTracking2.qll
Normal file
15
cpp/ql/src/semmle/code/cpp/ir/dataflow/TaintTracking2.qll
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Provides a `TaintTracking2` module, which is a copy of the `TaintTracking`
|
||||
* module. Use this class when data-flow configurations or taint-tracking
|
||||
* 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`. The
|
||||
* `TaintTracking::Configuration` class extends `DataFlow::Configuration`, and
|
||||
* `TaintTracking2::Configuration` extends `DataFlow2::Configuration`.
|
||||
*
|
||||
* See `semmle.code.cpp.ir.dataflow.TaintTracking` for the full documentation.
|
||||
*/
|
||||
module TaintTracking2 {
|
||||
import semmle.code.cpp.ir.dataflow.internal.tainttracking2.TaintTrackingImpl
|
||||
}
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,6 +156,11 @@ abstract class PostUpdateNode extends Node {
|
||||
abstract Node getPreUpdateNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node corresponding to `instr`.
|
||||
*/
|
||||
Node instructionNode(Instruction instr) { result.asInstruction() = instr }
|
||||
|
||||
/**
|
||||
* Gets a `Node` corresponding to `e` or any of its conversions. There is no
|
||||
* result if `e` is a `Conversion`.
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step.
|
||||
*/
|
||||
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
localAdditionalTaintStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||
* different objects.
|
||||
*/
|
||||
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
localInstructionTaintStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step.
|
||||
*/
|
||||
private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction nodeTo) {
|
||||
// Taint can flow through expressions that alter the value but preserve
|
||||
// more than one bit of it _or_ expressions that follow data through
|
||||
// pointer indirections.
|
||||
nodeTo.getAnOperand().getAnyDef() = nodeFrom and
|
||||
(
|
||||
nodeTo instanceof ArithmeticInstruction
|
||||
or
|
||||
nodeTo instanceof BitwiseInstruction
|
||||
or
|
||||
nodeTo instanceof PointerArithmeticInstruction
|
||||
or
|
||||
nodeTo instanceof FieldAddressInstruction
|
||||
or
|
||||
// The `CopyInstruction` case is also present in non-taint data flow, but
|
||||
// that uses `getDef` rather than `getAnyDef`. For taint, we want flow
|
||||
// from a definition of `myStruct` to a `myStruct.myField` expression.
|
||||
nodeTo instanceof CopyInstruction
|
||||
)
|
||||
or
|
||||
nodeTo.(LoadInstruction).getSourceAddress() = nodeFrom
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may propagate from `source` to `sink` in zero or more local
|
||||
* (intra-procedural) steps.
|
||||
*/
|
||||
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `e1` to `e2` in zero or more
|
||||
* local (intra-procedural) steps.
|
||||
*/
|
||||
predicate localExprTaint(Expr e1, Expr e2) {
|
||||
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be included in all
|
||||
* global taint flow configurations.
|
||||
*/
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
localAdditionalTaintStep(src, sink)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` should be a barrier in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintBarrier(DataFlow::Node node) { none() }
|
||||
@@ -0,0 +1,112 @@
|
||||
import TaintTrackingParameter::Public
|
||||
private import TaintTrackingParameter::Private
|
||||
|
||||
/**
|
||||
* A configuration of interprocedural taint tracking analysis. This defines
|
||||
* sources, sinks, and any other configurable aspect of the analysis. Each
|
||||
* use of the taint tracking library must define its own unique extension of
|
||||
* this abstract class.
|
||||
*
|
||||
* A taint-tracking configuration is a special data flow configuration
|
||||
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
|
||||
* necessarily preserve values but are still relevant from a taint tracking
|
||||
* perspective. (For example, string concatenation, where one of the operands
|
||||
* is tainted.)
|
||||
*
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
* // Optionally override `isSanitizer`.
|
||||
* // Optionally override `isSanitizerIn`.
|
||||
* // Optionally override `isSanitizerOut`.
|
||||
* // Optionally override `isSanitizerGuard`.
|
||||
* // Optionally override `isAdditionalTaintStep`.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
* Multiple configurations can coexist, but it is unsupported to depend on
|
||||
* another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the
|
||||
* overridden predicates that define sources, sinks, or additional steps.
|
||||
* Instead, the dependency should go to a `TaintTracking2::Configuration` or a
|
||||
* `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc.
|
||||
*/
|
||||
abstract class Configuration extends DataFlow::Configuration {
|
||||
bindingset[this]
|
||||
Configuration() { any() }
|
||||
|
||||
/**
|
||||
* Holds if `source` is a relevant taint source.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
defaultTaintBarrier(node)
|
||||
}
|
||||
|
||||
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
|
||||
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isSanitizerEdge(node1, node2)
|
||||
}
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may flow from `source` to `sink` for this configuration.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
super.hasFlow(source, sink)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import semmle.code.cpp.ir.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow as DataFlow
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import TaintTrackingParameter::Public
|
||||
private import TaintTrackingParameter::Private
|
||||
|
||||
/**
|
||||
* A configuration of interprocedural taint tracking analysis. This defines
|
||||
* sources, sinks, and any other configurable aspect of the analysis. Each
|
||||
* use of the taint tracking library must define its own unique extension of
|
||||
* this abstract class.
|
||||
*
|
||||
* A taint-tracking configuration is a special data flow configuration
|
||||
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
|
||||
* necessarily preserve values but are still relevant from a taint tracking
|
||||
* perspective. (For example, string concatenation, where one of the operands
|
||||
* is tainted.)
|
||||
*
|
||||
* To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string. For example, write
|
||||
*
|
||||
* ```
|
||||
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
* // Optionally override `isSanitizer`.
|
||||
* // Optionally override `isSanitizerIn`.
|
||||
* // Optionally override `isSanitizerOut`.
|
||||
* // Optionally override `isSanitizerGuard`.
|
||||
* // Optionally override `isAdditionalTaintStep`.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, to query whether there is flow between some `source` and `sink`,
|
||||
* write
|
||||
*
|
||||
* ```
|
||||
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
* ```
|
||||
*
|
||||
* Multiple configurations can coexist, but it is unsupported to depend on
|
||||
* another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the
|
||||
* overridden predicates that define sources, sinks, or additional steps.
|
||||
* Instead, the dependency should go to a `TaintTracking2::Configuration` or a
|
||||
* `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc.
|
||||
*/
|
||||
abstract class Configuration extends DataFlow::Configuration {
|
||||
bindingset[this]
|
||||
Configuration() { any() }
|
||||
|
||||
/**
|
||||
* Holds if `source` is a relevant taint source.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
defaultTaintBarrier(node)
|
||||
}
|
||||
|
||||
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
|
||||
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isSanitizerEdge(node1, node2)
|
||||
}
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint may flow from `source` to `sink` for this configuration.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||
super.hasFlow(source, sink)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import semmle.code.cpp.ir.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow2::DataFlow2 as DataFlow
|
||||
}
|
||||
@@ -9,32 +9,31 @@ private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
private predicate hasResultMemoryAccess(Instruction instr, IRVariable var, Type type, IntValue startBitOffset,
|
||||
IntValue endBitOffset) {
|
||||
private predicate hasResultMemoryAccess(
|
||||
Instruction instr, IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset
|
||||
) {
|
||||
resultPointsTo(instr.getResultAddress(), var, startBitOffset) and
|
||||
type = instr.getResultType() and
|
||||
if exists(instr.getResultSize()) then
|
||||
endBitOffset = Ints::add(startBitOffset, Ints::mul(instr.getResultSize(), 8))
|
||||
else
|
||||
endBitOffset = Ints::unknown()
|
||||
if exists(instr.getResultSize())
|
||||
then endBitOffset = Ints::add(startBitOffset, Ints::mul(instr.getResultSize(), 8))
|
||||
else endBitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private predicate hasOperandMemoryAccess(MemoryOperand operand, IRVariable var, Type type, IntValue startBitOffset,
|
||||
IntValue endBitOffset) {
|
||||
private predicate hasOperandMemoryAccess(
|
||||
MemoryOperand operand, IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset
|
||||
) {
|
||||
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, startBitOffset) and
|
||||
type = operand.getType() and
|
||||
if exists(operand.getSize()) then
|
||||
endBitOffset = Ints::add(startBitOffset, Ints::mul(operand.getSize(), 8))
|
||||
else
|
||||
endBitOffset = Ints::unknown()
|
||||
if exists(operand.getSize())
|
||||
then endBitOffset = Ints::add(startBitOffset, Ints::mul(operand.getSize(), 8))
|
||||
else endBitOffset = Ints::unknown()
|
||||
}
|
||||
|
||||
private newtype TMemoryLocation =
|
||||
TVariableMemoryLocation(IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset) {
|
||||
hasResultMemoryAccess(_, var, type, startBitOffset, endBitOffset) or
|
||||
hasOperandMemoryAccess(_, var, type, startBitOffset, endBitOffset)
|
||||
}
|
||||
or
|
||||
} or
|
||||
TUnknownMemoryLocation(IRFunction irFunc) or
|
||||
TUnknownVirtualVariable(IRFunction irFunc)
|
||||
|
||||
@@ -47,7 +46,7 @@ private newtype TMemoryLocation =
|
||||
*/
|
||||
abstract class MemoryLocation extends TMemoryLocation {
|
||||
abstract string toString();
|
||||
|
||||
|
||||
abstract VirtualVariable getVirtualVariable();
|
||||
|
||||
abstract Type getType();
|
||||
@@ -55,8 +54,7 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
abstract string getUniqueId();
|
||||
}
|
||||
|
||||
abstract class VirtualVariable extends MemoryLocation {
|
||||
}
|
||||
abstract class VirtualVariable extends MemoryLocation { }
|
||||
|
||||
/**
|
||||
* An access to memory within a single known `IRVariable`. The variable may be either an unescaped variable
|
||||
@@ -72,36 +70,28 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
|
||||
this = TVariableMemoryLocation(var, type, startBitOffset, endBitOffset)
|
||||
}
|
||||
|
||||
override final string toString() {
|
||||
result = var.toString() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" + type.toString() + ">"
|
||||
final override string toString() {
|
||||
result = var.toString() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" +
|
||||
type.toString() + ">"
|
||||
}
|
||||
|
||||
override final Type getType() {
|
||||
result = type
|
||||
}
|
||||
final override Type getType() { result = type }
|
||||
|
||||
final IntValue getStartBitOffset() {
|
||||
result = startBitOffset
|
||||
}
|
||||
|
||||
final IntValue getEndBitOffset() {
|
||||
result = endBitOffset
|
||||
}
|
||||
|
||||
final IRVariable getVariable() {
|
||||
result = var
|
||||
}
|
||||
final IntValue getStartBitOffset() { result = startBitOffset }
|
||||
|
||||
override final string getUniqueId() {
|
||||
final IntValue getEndBitOffset() { result = endBitOffset }
|
||||
|
||||
final IRVariable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = var.getUniqueId() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" +
|
||||
getTypeIdentityString(type) + ">"
|
||||
getTypeIdentityString(type) + ">"
|
||||
}
|
||||
|
||||
override final VirtualVariable getVirtualVariable() {
|
||||
if variableAddressEscapes(var) then
|
||||
result = TUnknownVirtualVariable(var.getEnclosingIRFunction())
|
||||
else
|
||||
result = TVariableMemoryLocation(var, var.getType(), 0, var.getType().getSize() * 8)
|
||||
final override VirtualVariable getVirtualVariable() {
|
||||
if variableAddressEscapes(var)
|
||||
then result = TUnknownVirtualVariable(var.getEnclosingIRFunction())
|
||||
else result = TVariableMemoryLocation(var, var.getType(), 0, var.getType().getSize() * 8)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,25 +122,15 @@ class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
|
||||
class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
|
||||
IRFunction irFunc;
|
||||
|
||||
UnknownMemoryLocation() {
|
||||
this = TUnknownMemoryLocation(irFunc)
|
||||
}
|
||||
|
||||
override final string toString() {
|
||||
result = "{Unknown}"
|
||||
}
|
||||
|
||||
override final VirtualVariable getVirtualVariable() {
|
||||
result = TUnknownVirtualVariable(irFunc)
|
||||
}
|
||||
UnknownMemoryLocation() { this = TUnknownMemoryLocation(irFunc) }
|
||||
|
||||
override final Type getType() {
|
||||
result instanceof UnknownType
|
||||
}
|
||||
final override string toString() { result = "{Unknown}" }
|
||||
|
||||
override final string getUniqueId() {
|
||||
result = "{Unknown}"
|
||||
}
|
||||
final override VirtualVariable getVirtualVariable() { result = TUnknownVirtualVariable(irFunc) }
|
||||
|
||||
final override Type getType() { result instanceof UnknownType }
|
||||
|
||||
final override string getUniqueId() { result = "{Unknown}" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,25 +139,15 @@ class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
|
||||
class UnknownVirtualVariable extends TUnknownVirtualVariable, VirtualVariable {
|
||||
IRFunction irFunc;
|
||||
|
||||
UnknownVirtualVariable() {
|
||||
this = TUnknownVirtualVariable(irFunc)
|
||||
}
|
||||
|
||||
override final string toString() {
|
||||
result = "{AllAliased}"
|
||||
}
|
||||
UnknownVirtualVariable() { this = TUnknownVirtualVariable(irFunc) }
|
||||
|
||||
override final Type getType() {
|
||||
result instanceof UnknownType
|
||||
}
|
||||
final override string toString() { result = "{AllAliased}" }
|
||||
|
||||
override final string getUniqueId() {
|
||||
result = " " + toString()
|
||||
}
|
||||
final override Type getType() { result instanceof UnknownType }
|
||||
|
||||
override final VirtualVariable getVirtualVariable() {
|
||||
result = this
|
||||
}
|
||||
final override string getUniqueId() { result = " " + toString() }
|
||||
|
||||
final override VirtualVariable getVirtualVariable() { result = this }
|
||||
}
|
||||
|
||||
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
@@ -185,44 +155,44 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
(
|
||||
// An UnknownVirtualVariable must totally overlap any location within the same virtual variable.
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
def instanceof UnknownVirtualVariable and result instanceof MustTotallyOverlap
|
||||
def instanceof UnknownVirtualVariable and
|
||||
result instanceof MustTotallyOverlap
|
||||
or
|
||||
// An UnknownMemoryLocation may partially overlap any Location within the same virtual variable.
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
def instanceof UnknownMemoryLocation and result instanceof MayPartiallyOverlap
|
||||
def instanceof UnknownMemoryLocation and
|
||||
result instanceof MayPartiallyOverlap
|
||||
or
|
||||
exists(VariableMemoryLocation defVariableLocation |
|
||||
defVariableLocation = def and
|
||||
(
|
||||
(
|
||||
// A VariableMemoryLocation may partially overlap an unknown location within the same virtual variable.
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
((use instanceof UnknownMemoryLocation) or (use instanceof UnknownVirtualVariable)) and
|
||||
result instanceof MayPartiallyOverlap
|
||||
) or
|
||||
// A VariableMemoryLocation may partially overlap an unknown location within the same virtual variable.
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
(use instanceof UnknownMemoryLocation or use instanceof UnknownVirtualVariable) and
|
||||
result instanceof MayPartiallyOverlap
|
||||
or
|
||||
// A VariableMemoryLocation overlaps another location within the same variable based on the relationship
|
||||
// of the two offset intervals.
|
||||
exists(Overlap intervalOverlap |
|
||||
intervalOverlap = getVariableMemoryLocationOverlap(def, use) and
|
||||
if intervalOverlap instanceof MustExactlyOverlap then (
|
||||
if def.getType() = use.getType() then (
|
||||
if intervalOverlap instanceof MustExactlyOverlap
|
||||
then
|
||||
if def.getType() = use.getType()
|
||||
then
|
||||
// The def and use types match, so it's an exact overlap.
|
||||
result instanceof MustExactlyOverlap
|
||||
)
|
||||
else (
|
||||
else
|
||||
// The def and use types are not the same, so it's just a total overlap.
|
||||
result instanceof MustTotallyOverlap
|
||||
)
|
||||
)
|
||||
else if defVariableLocation.coversEntireVariable() then (
|
||||
// The definition covers the entire variable, so assume that it totally overlaps the use, even if the
|
||||
// interval for the use is unknown or outside the bounds of the variable.
|
||||
result instanceof MustTotallyOverlap
|
||||
)
|
||||
else (
|
||||
// Just use the overlap relation of the interval.
|
||||
result = intervalOverlap
|
||||
)
|
||||
else
|
||||
if defVariableLocation.coversEntireVariable()
|
||||
then
|
||||
// The definition covers the entire variable, so assume that it totally overlaps the use, even if the
|
||||
// interval for the use is unknown or outside the bounds of the variable.
|
||||
result instanceof MustTotallyOverlap
|
||||
else
|
||||
// Just use the overlap relation of the interval.
|
||||
result = intervalOverlap
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -245,10 +215,9 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
* 5. In `getVariableMemoryLocationOverlap`, compute the precise overlap relation for each
|
||||
* overlapping pair of VMLs (linear in the size of the overlap set)
|
||||
*/
|
||||
|
||||
private predicate isRelevantOffset(VirtualVariable vv, IntValue offset) {
|
||||
exists(VariableMemoryLocation ml |
|
||||
ml.getVirtualVariable() = vv
|
||||
|
|
||||
exists(VariableMemoryLocation ml | ml.getVirtualVariable() = vv |
|
||||
ml.getStartBitOffset() = offset
|
||||
or
|
||||
ml.getEndBitOffset() = offset
|
||||
@@ -278,50 +247,55 @@ private predicate hasUnknownOffset(VariableMemoryLocation vml, VirtualVariable v
|
||||
)
|
||||
}
|
||||
|
||||
private predicate overlappingVariableMemoryLocations(VariableMemoryLocation def, VariableMemoryLocation use) {
|
||||
exists(VirtualVariable vv, int offsetRank | isCoveredOffset(def, vv, offsetRank) and isCoveredOffset(use, vv, offsetRank))
|
||||
or
|
||||
hasUnknownOffset(def, use.getVirtualVariable())
|
||||
or
|
||||
hasUnknownOffset(use, def.getVirtualVariable())
|
||||
private predicate overlappingVariableMemoryLocations(
|
||||
VariableMemoryLocation def, VariableMemoryLocation use
|
||||
) {
|
||||
exists(VirtualVariable vv, int offsetRank |
|
||||
isCoveredOffset(def, vv, offsetRank) and isCoveredOffset(use, vv, offsetRank)
|
||||
)
|
||||
or
|
||||
hasUnknownOffset(def, use.getVirtualVariable())
|
||||
or
|
||||
hasUnknownOffset(use, def.getVirtualVariable())
|
||||
}
|
||||
|
||||
pragma[noopt] // Internal ticket: QL-937
|
||||
private predicate overlappingIRVariableMemoryLocations(VariableMemoryLocation def, VariableMemoryLocation use) {
|
||||
// Internal ticket: QL-937
|
||||
pragma[noopt]
|
||||
private predicate overlappingIRVariableMemoryLocations(
|
||||
VariableMemoryLocation def, VariableMemoryLocation use
|
||||
) {
|
||||
overlappingVariableMemoryLocations(def, use) and
|
||||
def.getVariable() = use.getVariable()
|
||||
}
|
||||
|
||||
private Overlap getVariableMemoryLocationOverlap(VariableMemoryLocation def, VariableMemoryLocation use) {
|
||||
private Overlap getVariableMemoryLocationOverlap(
|
||||
VariableMemoryLocation def, VariableMemoryLocation use
|
||||
) {
|
||||
overlappingIRVariableMemoryLocations(def, use) and
|
||||
result = Interval::getOverlap(def.getStartBitOffset(), def.getEndBitOffset(), use.getStartBitOffset(), use.getEndBitOffset())
|
||||
result = Interval::getOverlap(def.getStartBitOffset(), def.getEndBitOffset(),
|
||||
use.getStartBitOffset(), use.getEndBitOffset())
|
||||
}
|
||||
|
||||
|
||||
MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
exists(MemoryAccessKind kind |
|
||||
kind = instr.getResultMemoryAccess() and
|
||||
(
|
||||
(
|
||||
kind.usesAddressOperand() and
|
||||
if hasResultMemoryAccess(instr, _, _, _, _) then (
|
||||
if hasResultMemoryAccess(instr, _, _, _, _)
|
||||
then
|
||||
exists(IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset |
|
||||
hasResultMemoryAccess(instr, var, type, startBitOffset, endBitOffset) and
|
||||
result = TVariableMemoryLocation(var, type, startBitOffset, endBitOffset)
|
||||
)
|
||||
)
|
||||
else (
|
||||
result = TUnknownMemoryLocation(instr.getEnclosingIRFunction())
|
||||
)
|
||||
) or
|
||||
(
|
||||
kind instanceof EscapedMemoryAccess and
|
||||
result = TUnknownVirtualVariable(instr.getEnclosingIRFunction())
|
||||
) or
|
||||
(
|
||||
kind instanceof EscapedMayMemoryAccess and
|
||||
result = TUnknownMemoryLocation(instr.getEnclosingIRFunction())
|
||||
else result = TUnknownMemoryLocation(instr.getEnclosingIRFunction())
|
||||
)
|
||||
or
|
||||
kind instanceof EscapedMemoryAccess and
|
||||
result = TUnknownVirtualVariable(instr.getEnclosingIRFunction())
|
||||
or
|
||||
kind instanceof EscapedMayMemoryAccess and
|
||||
result = TUnknownMemoryLocation(instr.getEnclosingIRFunction())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -332,24 +306,20 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
(
|
||||
(
|
||||
kind.usesAddressOperand() and
|
||||
if hasOperandMemoryAccess(operand, _, _, _, _) then (
|
||||
if hasOperandMemoryAccess(operand, _, _, _, _)
|
||||
then
|
||||
exists(IRVariable var, Type type, IntValue startBitOffset, IntValue endBitOffset |
|
||||
hasOperandMemoryAccess(operand, var, type, startBitOffset, endBitOffset) and
|
||||
result = TVariableMemoryLocation(var, type, startBitOffset, endBitOffset)
|
||||
)
|
||||
)
|
||||
else (
|
||||
result = TUnknownMemoryLocation(operand.getEnclosingIRFunction())
|
||||
)
|
||||
) or
|
||||
(
|
||||
kind instanceof EscapedMemoryAccess and
|
||||
result = TUnknownVirtualVariable(operand.getEnclosingIRFunction())
|
||||
) or
|
||||
(
|
||||
kind instanceof EscapedMayMemoryAccess and
|
||||
result = TUnknownMemoryLocation(operand.getEnclosingIRFunction())
|
||||
else result = TUnknownMemoryLocation(operand.getEnclosingIRFunction())
|
||||
)
|
||||
or
|
||||
kind instanceof EscapedMemoryAccess and
|
||||
result = TUnknownVirtualVariable(operand.getEnclosingIRFunction())
|
||||
or
|
||||
kind instanceof EscapedMayMemoryAccess and
|
||||
result = TUnknownMemoryLocation(operand.getEnclosingIRFunction())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
exists(MemoryLocation location |
|
||||
location = getResultMemoryLocation(instruction) and
|
||||
(
|
||||
key = "ResultMemoryLocation" and result = location.toString() or
|
||||
key = "ResultMemoryLocation" and result = location.toString()
|
||||
or
|
||||
key = "ResultVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
)
|
||||
)
|
||||
@@ -21,33 +22,40 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
exists(MemoryLocation location |
|
||||
location = getOperandMemoryLocation(instruction.getAnOperand()) and
|
||||
(
|
||||
key = "OperandMemoryAccess" and result = location.toString() or
|
||||
key = "OperandMemoryAccess" and result = location.toString()
|
||||
or
|
||||
key = "OperandVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionRank[" + useLocation.toString() + "]" and
|
||||
result = defRank.toString()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock useBlock, int useRank |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, instruction) and
|
||||
key = "UseRank[" + useLocation.toString() + "]" and
|
||||
result = useRank.toString()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionReachesUse[" + useLocation.toString() + "]" and
|
||||
result = strictconcat(IRBlock useBlock, int useRank, int useIndex |
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, defBlock, defRank, useBlock, useRank)
|
||||
) |
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", " order by useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, defBlock, defRank, useBlock, useRank)
|
||||
)
|
||||
|
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", "
|
||||
order by
|
||||
useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -57,53 +65,62 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
defIndex = -1 and
|
||||
key = "DefinitionRank(Phi)[" + useLocation.toString() + "]" and
|
||||
result = defRank.toString()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, MemoryLocation defLocation, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, defLocation, block, defRank, defIndex) and
|
||||
defIndex = -1 and
|
||||
key = "DefinitionReachesUse(Phi)[" + useLocation.toString() + "]" and
|
||||
result = strictconcat(IRBlock useBlock, int useRank, int useIndex |
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, block, defRank, useBlock, useRank) and
|
||||
exists(getOverlap(defLocation, useLocation))
|
||||
) |
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", " order by useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
) or
|
||||
exists(MemoryLocation useLocation, IRBlock predBlock, IRBlock defBlock, int defIndex, Overlap overlap |
|
||||
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex, overlap) and
|
||||
key = "PhiUse[" + useLocation.toString() + " from " + predBlock.getDisplayIndex().toString() + "]" and
|
||||
result = defBlock.getDisplayIndex().toString() + "_" + defIndex + " (" + overlap.toString() + ")"
|
||||
) or
|
||||
(
|
||||
key = "LiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnEntryToBlock(useLocation, block) |
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
) or
|
||||
(
|
||||
key = "LiveOnExit" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnExitFromBlock(useLocation, block) |
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
) or
|
||||
(
|
||||
key = "DefsLiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnEntryToBlock(defLocation, block) |
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
) or
|
||||
(
|
||||
key = "DefsLiveOnExit" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnExitFromBlock(defLocation, block) |
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, block, defRank, useBlock, useRank) and
|
||||
exists(getOverlap(defLocation, useLocation))
|
||||
)
|
||||
|
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", "
|
||||
order by
|
||||
useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
MemoryLocation useLocation, IRBlock predBlock, IRBlock defBlock, int defIndex, Overlap overlap
|
||||
|
|
||||
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex, overlap) and
|
||||
key = "PhiUse[" + useLocation.toString() + " from " + predBlock.getDisplayIndex().toString() +
|
||||
"]" and
|
||||
result = defBlock.getDisplayIndex().toString() + "_" + defIndex + " (" + overlap.toString() +
|
||||
")"
|
||||
)
|
||||
or
|
||||
key = "LiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnEntryToBlock(useLocation, block)
|
||||
|
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
or
|
||||
key = "LiveOnExit" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnExitFromBlock(useLocation, block)
|
||||
|
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
or
|
||||
key = "DefsLiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnEntryToBlock(defLocation, block)
|
||||
|
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
or
|
||||
key = "DefsLiveOnExit" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnExitFromBlock(defLocation, block)
|
||||
|
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,31 +6,32 @@ private import semmle.code.cpp.ir.internal.Overlap
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
cached private module Cached {
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
private IRBlock getNewBlock(OldBlock oldBlock) {
|
||||
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
}
|
||||
|
||||
cached predicate functionHasIR(Function func) {
|
||||
exists(OldIR::IRFunction irFunc |
|
||||
irFunc.getFunction() = func
|
||||
)
|
||||
cached
|
||||
predicate functionHasIR(Function func) {
|
||||
exists(OldIR::IRFunction irFunc | irFunc.getFunction() = func)
|
||||
}
|
||||
|
||||
cached OldInstruction getOldInstruction(Instruction instr) {
|
||||
instr = WrappedInstruction(result)
|
||||
}
|
||||
cached
|
||||
OldInstruction getOldInstruction(Instruction instr) { instr = WrappedInstruction(result) }
|
||||
|
||||
private IRVariable getNewIRVariable(OldIR::IRVariable var) {
|
||||
// This is just a type cast. Both classes derive from the same newtype.
|
||||
result = var
|
||||
}
|
||||
|
||||
cached newtype TInstruction =
|
||||
cached
|
||||
newtype TInstruction =
|
||||
WrappedInstruction(OldInstruction oldInstruction) {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction
|
||||
} or
|
||||
@@ -48,8 +49,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
|
||||
Type type) {
|
||||
cached
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) {
|
||||
exists(OldIR::IRTempVariable var |
|
||||
var.getEnclosingFunction() = func and
|
||||
var.getAST() = ast and
|
||||
@@ -58,13 +59,15 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate hasModeledMemoryResult(Instruction instruction) {
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) {
|
||||
exists(Alias::getResultMemoryLocation(getOldInstruction(instruction))) or
|
||||
instruction instanceof PhiInstruction or // Phis always have modeled results
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
instruction instanceof PhiInstruction or // Phis always have modeled results
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
@@ -73,16 +76,22 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getMemoryOperandDefinition(Instruction instruction, MemoryOperandTag tag, Overlap overlap) {
|
||||
cached
|
||||
Instruction getMemoryOperandDefinition(
|
||||
Instruction instruction, MemoryOperandTag tag, Overlap overlap
|
||||
) {
|
||||
exists(OldInstruction oldInstruction, OldIR::NonPhiMemoryOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
(
|
||||
(
|
||||
if exists(Alias::getOperandMemoryLocation(oldOperand)) then (
|
||||
exists(OldBlock useBlock, int useRank, Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation,
|
||||
OldBlock defBlock, int defRank, int defOffset |
|
||||
if exists(Alias::getOperandMemoryLocation(oldOperand))
|
||||
then
|
||||
exists(
|
||||
OldBlock useBlock, int useRank, Alias::MemoryLocation useLocation,
|
||||
Alias::MemoryLocation defLocation, OldBlock defBlock, int defRank, int defOffset
|
||||
|
|
||||
useLocation = Alias::getOperandMemoryLocation(oldOperand) and
|
||||
hasDefinitionAtRank(useLocation, defLocation, defBlock, defRank, defOffset) and
|
||||
hasUseAtRank(useLocation, useBlock, useRank, oldInstruction) and
|
||||
@@ -90,12 +99,12 @@ cached private module Cached {
|
||||
overlap = Alias::getOverlap(defLocation, useLocation) and
|
||||
result = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation)
|
||||
)
|
||||
)
|
||||
else (
|
||||
result = instruction.getEnclosingIRFunction().getUnmodeledDefinitionInstruction() and
|
||||
overlap instanceof MustTotallyOverlap
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
// Connect any definitions that are not being modeled in SSA to the
|
||||
// `UnmodeledUse` instruction.
|
||||
exists(OldInstruction oldDefinition |
|
||||
@@ -107,7 +116,8 @@ cached private module Cached {
|
||||
overlap instanceof MustTotallyOverlap
|
||||
)
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
instruction = Chi(getOldInstruction(result)) and
|
||||
tag instanceof ChiPartialOperandTag and
|
||||
overlap instanceof MustExactlyOverlap
|
||||
@@ -124,7 +134,8 @@ cached private module Cached {
|
||||
overlap instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
cached Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
cached
|
||||
Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::TypedOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
@@ -133,7 +144,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
|
||||
cached
|
||||
int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::SideEffectOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
@@ -144,20 +156,28 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPhiOperandDefinition(PhiInstruction instr,
|
||||
IRBlock newPredecessorBlock, Overlap overlap) {
|
||||
exists(Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation, OldBlock phiBlock, OldBlock predBlock,
|
||||
OldBlock defBlock, int defOffset |
|
||||
hasPhiOperandDefinition(defLocation, useLocation, phiBlock, predBlock, defBlock, defOffset, overlap) and
|
||||
cached
|
||||
Instruction getPhiOperandDefinition(
|
||||
PhiInstruction instr, IRBlock newPredecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(
|
||||
Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation, OldBlock phiBlock,
|
||||
OldBlock predBlock, OldBlock defBlock, int defOffset
|
||||
|
|
||||
hasPhiOperandDefinition(defLocation, useLocation, phiBlock, predBlock, defBlock, defOffset,
|
||||
overlap) and
|
||||
instr = Phi(phiBlock, useLocation) and
|
||||
newPredecessorBlock = getNewBlock(predBlock) and
|
||||
result = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation)
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
|
||||
exists(Alias::VirtualVariable vvar, OldInstruction oldInstr, Alias::MemoryLocation defLocation, OldBlock defBlock,
|
||||
int defRank, int defOffset, OldBlock useBlock, int useRank |
|
||||
cached
|
||||
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
|
||||
exists(
|
||||
Alias::VirtualVariable vvar, OldInstruction oldInstr, Alias::MemoryLocation defLocation,
|
||||
OldBlock defBlock, int defRank, int defOffset, OldBlock useBlock, int useRank
|
||||
|
|
||||
chiInstr = Chi(oldInstr) and
|
||||
vvar = Alias::getResultMemoryLocation(oldInstr).getVirtualVariable() and
|
||||
hasDefinitionAtRank(vvar, defLocation, defBlock, defRank, defOffset) and
|
||||
@@ -167,28 +187,32 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
|
||||
cached
|
||||
Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
|
||||
exists(OldBlock oldBlock |
|
||||
instr = Phi(oldBlock, _) and
|
||||
result = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
)
|
||||
}
|
||||
|
||||
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
cached
|
||||
Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getConvertedResultExpression()
|
||||
}
|
||||
|
||||
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
cached
|
||||
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
|
||||
* that node is its successor in the new successor relation, and the Chi node's successors are
|
||||
* the new instructions generated from the successors of the old instruction
|
||||
*/
|
||||
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
if(hasChiNode(_, getOldInstruction(instruction)))
|
||||
cached
|
||||
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
if hasChiNode(_, getOldInstruction(instruction))
|
||||
then
|
||||
result = Chi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -196,14 +220,12 @@ cached private module Cached {
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then (
|
||||
result = Unreached(instruction.getEnclosingFunction())
|
||||
)
|
||||
else (
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = Unreached(instruction.getEnclosingFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = Chi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
@@ -211,7 +233,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
cached
|
||||
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
not Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) and
|
||||
// There is only one case for the translation into `result` because the
|
||||
@@ -228,7 +251,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Locatable getInstructionAST(Instruction instruction) {
|
||||
cached
|
||||
Locatable getInstructionAST(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction)
|
||||
or
|
||||
@@ -245,13 +269,12 @@ cached private module Cached {
|
||||
instruction = Unreached(result)
|
||||
}
|
||||
|
||||
cached predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
cached
|
||||
predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction) and
|
||||
type = oldInstruction.getResultType() and
|
||||
if oldInstruction.isGLValue()
|
||||
then isGLValue = true
|
||||
else isGLValue = false
|
||||
if oldInstruction.isGLValue() then isGLValue = true else isGLValue = false
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction, Alias::VirtualVariable vvar |
|
||||
@@ -272,7 +295,8 @@ cached private module Cached {
|
||||
isGLValue = false
|
||||
}
|
||||
|
||||
cached Opcode getInstructionOpcode(Instruction instruction) {
|
||||
cached
|
||||
Opcode getInstructionOpcode(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction) and
|
||||
result = oldInstruction.getOpcode()
|
||||
@@ -288,7 +312,8 @@ cached private module Cached {
|
||||
result instanceof Opcode::Unreached
|
||||
}
|
||||
|
||||
cached IRFunction getInstructionEnclosingIRFunction(Instruction instruction) {
|
||||
cached
|
||||
IRFunction getInstructionEnclosingIRFunction(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction)
|
||||
or
|
||||
@@ -305,46 +330,59 @@ cached private module Cached {
|
||||
instruction = Unreached(result.getFunction())
|
||||
}
|
||||
|
||||
cached IRVariable getInstructionVariable(Instruction instruction) {
|
||||
result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable())
|
||||
cached
|
||||
IRVariable getInstructionVariable(Instruction instruction) {
|
||||
result = getNewIRVariable(getOldInstruction(instruction)
|
||||
.(OldIR::VariableInstruction)
|
||||
.getVariable())
|
||||
}
|
||||
|
||||
cached Field getInstructionField(Instruction instruction) {
|
||||
cached
|
||||
Field getInstructionField(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
|
||||
}
|
||||
|
||||
cached Function getInstructionFunction(Instruction instruction) {
|
||||
cached
|
||||
Function getInstructionFunction(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
cached string getInstructionConstantValue(Instruction instruction) {
|
||||
cached
|
||||
string getInstructionConstantValue(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
|
||||
}
|
||||
|
||||
cached StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
cached
|
||||
StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::BuiltInOperationInstruction).getBuiltInOperation()
|
||||
cached
|
||||
BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
.(OldIR::BuiltInOperationInstruction)
|
||||
.getBuiltInOperation()
|
||||
}
|
||||
|
||||
cached Type getInstructionExceptionType(Instruction instruction) {
|
||||
cached
|
||||
Type getInstructionExceptionType(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
|
||||
}
|
||||
|
||||
cached int getInstructionElementSize(Instruction instruction) {
|
||||
cached
|
||||
int getInstructionElementSize(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize()
|
||||
}
|
||||
|
||||
cached int getInstructionResultSize(Instruction instruction) {
|
||||
cached
|
||||
int getInstructionResultSize(Instruction instruction) {
|
||||
// Only return a result for instructions that needed an explicit result size.
|
||||
instruction.getResultType() instanceof UnknownType and
|
||||
result = getOldInstruction(instruction).getResultSize()
|
||||
}
|
||||
|
||||
cached predicate getInstructionInheritance(Instruction instruction, Class baseClass,
|
||||
Class derivedClass) {
|
||||
cached
|
||||
predicate getInstructionInheritance(Instruction instruction, Class baseClass, Class derivedClass) {
|
||||
exists(OldIR::InheritanceConversionInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instruction) and
|
||||
baseClass = oldInstr.getBaseClass() and
|
||||
@@ -352,7 +390,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
cached
|
||||
Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
exists(OldIR::SideEffectInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
|
||||
@@ -365,9 +404,7 @@ cached private module Cached {
|
||||
}
|
||||
}
|
||||
|
||||
private Instruction getNewInstruction(OldInstruction instr) {
|
||||
getOldInstruction(result) = instr
|
||||
}
|
||||
private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(result) = instr }
|
||||
|
||||
/**
|
||||
* Holds if instruction `def` needs to have a `Chi` instruction inserted after it, to account for a partial definition
|
||||
@@ -413,16 +450,18 @@ private module PhiInsertion {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the memory location `defLocation` has a definition in block `block`, either because of an existing
|
||||
* instruction, a `Phi` node, or a `Chi` node.
|
||||
*/
|
||||
* Holds if the memory location `defLocation` has a definition in block `block`, either because of an existing
|
||||
* instruction, a `Phi` node, or a `Chi` node.
|
||||
*/
|
||||
private predicate definitionHasDefinitionInBlock(Alias::MemoryLocation defLocation, OldBlock block) {
|
||||
definitionHasPhiNode(defLocation, block) or
|
||||
definitionHasPhiNode(defLocation, block)
|
||||
or
|
||||
exists(OldInstruction def, Alias::MemoryLocation resultLocation |
|
||||
def.getBlock() = block and
|
||||
resultLocation = Alias::getResultMemoryLocation(def) and
|
||||
(
|
||||
defLocation = resultLocation or
|
||||
defLocation = resultLocation
|
||||
or
|
||||
// For a virtual variable, any definition of a member location will either generate a `Chi` node that defines
|
||||
// the virtual variable, or will totally overlap the virtual variable. Either way, treat this as a definition of
|
||||
// the virtual variable.
|
||||
@@ -438,16 +477,17 @@ private module PhiInsertion {
|
||||
private predicate definitionHasUse(Alias::MemoryLocation defLocation, OldBlock block, int index) {
|
||||
exists(OldInstruction use |
|
||||
block.getInstruction(index) = use and
|
||||
if defLocation instanceof Alias::VirtualVariable then (
|
||||
if defLocation instanceof Alias::VirtualVariable
|
||||
then (
|
||||
exists(Alias::MemoryLocation useLocation |
|
||||
// For a virtual variable, any use of a location that is a member of the virtual variable counts as a use.
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
|
||||
defLocation = useLocation.getVirtualVariable()
|
||||
) or
|
||||
// For a virtual variable, any use of a location that is a member of the virtual variable counts as a use.
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
|
||||
defLocation = useLocation.getVirtualVariable()
|
||||
)
|
||||
or
|
||||
// A `Chi` instruction consumes the enclosing virtual variable of its use location.
|
||||
hasChiNode(defLocation, use)
|
||||
)
|
||||
else (
|
||||
) else (
|
||||
// For other locations, only an exactly-overlapping use of the same location counts as a use.
|
||||
defLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
|
||||
Alias::getOverlap(defLocation, defLocation) instanceof MustExactlyOverlap
|
||||
@@ -460,11 +500,14 @@ private module PhiInsertion {
|
||||
* there is a definition that would prevent a previous definition of `defLocation` from being consumed as the operand
|
||||
* of a `Phi` node that occurs after the redefinition.
|
||||
*/
|
||||
private predicate definitionHasRedefinition(Alias::MemoryLocation defLocation, OldBlock block, int index) {
|
||||
private predicate definitionHasRedefinition(
|
||||
Alias::MemoryLocation defLocation, OldBlock block, int index
|
||||
) {
|
||||
exists(OldInstruction redef, Alias::MemoryLocation redefLocation |
|
||||
block.getInstruction(index) = redef and
|
||||
redefLocation = Alias::getResultMemoryLocation(redef) and
|
||||
if defLocation instanceof Alias::VirtualVariable then (
|
||||
if defLocation instanceof Alias::VirtualVariable
|
||||
then
|
||||
// For a virtual variable, the definition may be consumed by any use of a location that is a member of the
|
||||
// virtual variable. Thus, the definition is live until a subsequent redefinition of the entire virtual
|
||||
// variable.
|
||||
@@ -472,20 +515,18 @@ private module PhiInsertion {
|
||||
overlap = Alias::getOverlap(redefLocation, defLocation) and
|
||||
not overlap instanceof MayPartiallyOverlap
|
||||
)
|
||||
)
|
||||
else (
|
||||
else
|
||||
// For other locations, the definition may only be consumed by an exactly-overlapping use of the same location.
|
||||
// Thus, the definition is live until a subsequent definition of any location that may overlap the original
|
||||
// definition location.
|
||||
exists(Alias::getOverlap(redefLocation, defLocation))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the definition `defLocation` is live on entry to block `block`. The definition is live if there is at
|
||||
* least one use of that definition before any intervening instruction that redefines the definition location.
|
||||
*/
|
||||
* Holds if the definition `defLocation` is live on entry to block `block`. The definition is live if there is at
|
||||
* least one use of that definition before any intervening instruction that redefines the definition location.
|
||||
*/
|
||||
predicate definitionLiveOnEntryToBlock(Alias::MemoryLocation defLocation, OldBlock block) {
|
||||
exists(int firstAccess |
|
||||
definitionHasUse(defLocation, block, firstAccess) and
|
||||
@@ -496,7 +537,8 @@ private module PhiInsertion {
|
||||
)
|
||||
)
|
||||
or
|
||||
(definitionLiveOnExitFromBlock(defLocation, block) and not definitionHasRedefinition(defLocation, block, _))
|
||||
definitionLiveOnExitFromBlock(defLocation, block) and
|
||||
not definitionHasRedefinition(defLocation, block, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,7 +558,7 @@ private import DefUse
|
||||
* computed separately for each unique use `MemoryLocation`. An instruction is treated as a definition of a use location
|
||||
* if the defined location overlaps the use location in any way. Thus, a single instruction may serve as a definition
|
||||
* for multiple use locations, since a single definition location may overlap many use locations.
|
||||
*
|
||||
*
|
||||
* Definitions and uses are identified by a block and an integer "offset". An offset of -1 indicates the definition
|
||||
* from a `Phi` instruction at the beginning of the block. An offset of 2*i indicates a definition or use on the
|
||||
* instruction at index `i` in the block. An offset of 2*i+1 indicates a definition or use on the `Chi` instruction that
|
||||
@@ -532,47 +574,46 @@ module DefUse {
|
||||
/**
|
||||
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
|
||||
*/
|
||||
pragma[inline]
|
||||
bindingset[defOffset, defLocation]
|
||||
Instruction getDefinitionOrChiInstruction(OldBlock defBlock, int defOffset,
|
||||
Alias::MemoryLocation defLocation) {
|
||||
(
|
||||
defOffset >= 0 and
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = defBlock.getInstruction(defOffset / 2) and
|
||||
if (defOffset % 2) > 0 then (
|
||||
// An odd offset corresponds to the `Chi` instruction.
|
||||
result = Chi(oldInstr)
|
||||
)
|
||||
else (
|
||||
// An even offset corresponds to the original instruction.
|
||||
result = getNewInstruction(oldInstr)
|
||||
)
|
||||
)
|
||||
) or
|
||||
(
|
||||
defOffset < 0 and
|
||||
result = Phi(defBlock, defLocation)
|
||||
pragma[inline]
|
||||
Instruction getDefinitionOrChiInstruction(
|
||||
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation
|
||||
) {
|
||||
defOffset >= 0 and
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = defBlock.getInstruction(defOffset / 2) and
|
||||
if (defOffset % 2) > 0
|
||||
then
|
||||
// An odd offset corresponds to the `Chi` instruction.
|
||||
result = Chi(oldInstr)
|
||||
else
|
||||
// An even offset corresponds to the original instruction.
|
||||
result = getNewInstruction(oldInstr)
|
||||
)
|
||||
or
|
||||
defOffset < 0 and
|
||||
result = Phi(defBlock, defLocation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
*/
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
*/
|
||||
private int exitRank(Alias::MemoryLocation useLocation, OldBlock block) {
|
||||
result = max(int rankIndex | defUseRank(useLocation, block, rankIndex, _)) + 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`, where `defBlock` and
|
||||
* `useBlock` are the same block.
|
||||
*/
|
||||
private predicate definitionReachesUseWithinBlock(Alias::MemoryLocation useLocation, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`, where `defBlock` and
|
||||
* `useBlock` are the same block.
|
||||
*/
|
||||
private predicate definitionReachesUseWithinBlock(
|
||||
Alias::MemoryLocation useLocation, OldBlock defBlock, int defRank, OldBlock useBlock,
|
||||
int useRank
|
||||
) {
|
||||
defBlock = useBlock and
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, _) and
|
||||
hasUseAtRank(useLocation, useBlock, useRank, _) and
|
||||
@@ -580,59 +621,58 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesUse(Alias::MemoryLocation useLocation, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesUse(
|
||||
Alias::MemoryLocation useLocation, OldBlock defBlock, int defRank, OldBlock useBlock,
|
||||
int useRank
|
||||
) {
|
||||
hasUseAtRank(useLocation, useBlock, useRank, _) and
|
||||
(
|
||||
definitionReachesUseWithinBlock(useLocation, defBlock, defRank, useBlock,
|
||||
useRank) or
|
||||
(
|
||||
definitionReachesEndOfBlock(useLocation, defBlock, defRank,
|
||||
useBlock.getAFeasiblePredecessor()) and
|
||||
not definitionReachesUseWithinBlock(useLocation, useBlock, _, useBlock, useRank)
|
||||
)
|
||||
definitionReachesUseWithinBlock(useLocation, defBlock, defRank, useBlock, useRank)
|
||||
or
|
||||
definitionReachesEndOfBlock(useLocation, defBlock, defRank, useBlock.getAFeasiblePredecessor()) and
|
||||
not definitionReachesUseWithinBlock(useLocation, useBlock, _, useBlock, useRank)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the definition that overlaps `useLocation` at `(block, defRank)` reaches the rank
|
||||
* index `reachesRank` in block `block`.
|
||||
*/
|
||||
private predicate definitionReachesRank(Alias::MemoryLocation useLocation, OldBlock block, int defRank,
|
||||
int reachesRank) {
|
||||
* Holds if the definition that overlaps `useLocation` at `(block, defRank)` reaches the rank
|
||||
* index `reachesRank` in block `block`.
|
||||
*/
|
||||
private predicate definitionReachesRank(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int defRank, int reachesRank
|
||||
) {
|
||||
hasDefinitionAtRank(useLocation, _, block, defRank, _) and
|
||||
reachesRank <= exitRank(useLocation, block) and // Without this, the predicate would be infinite.
|
||||
reachesRank <= exitRank(useLocation, block) and // Without this, the predicate would be infinite.
|
||||
(
|
||||
// The def always reaches the next use, even if there is also a def on the
|
||||
// use instruction.
|
||||
reachesRank = defRank + 1 or
|
||||
(
|
||||
// If the def reached the previous rank, it also reaches the current rank,
|
||||
// unless there was another def at the previous rank.
|
||||
definitionReachesRank(useLocation, block, defRank, reachesRank - 1) and
|
||||
not hasDefinitionAtRank(useLocation, _, block, reachesRank - 1, _)
|
||||
)
|
||||
reachesRank = defRank + 1
|
||||
or
|
||||
// If the def reached the previous rank, it also reaches the current rank,
|
||||
// unless there was another def at the previous rank.
|
||||
definitionReachesRank(useLocation, block, defRank, reachesRank - 1) and
|
||||
not hasDefinitionAtRank(useLocation, _, block, reachesRank - 1, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the definition that overlaps `useLocation` at `(defBlock, defRank)` reaches the end of
|
||||
* block `block` without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesEndOfBlock(Alias::MemoryLocation useLocation, OldBlock defBlock,
|
||||
int defRank, OldBlock block) {
|
||||
* Holds if the definition that overlaps `useLocation` at `(defBlock, defRank)` reaches the end of
|
||||
* block `block` without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesEndOfBlock(
|
||||
Alias::MemoryLocation useLocation, OldBlock defBlock, int defRank, OldBlock block
|
||||
) {
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, _) and
|
||||
(
|
||||
(
|
||||
// If we're looking at the def's own block, just see if it reaches the exit
|
||||
// rank of the block.
|
||||
block = defBlock and
|
||||
locationLiveOnExitFromBlock(useLocation, defBlock) and
|
||||
definitionReachesRank(useLocation, defBlock, defRank, exitRank(useLocation, defBlock))
|
||||
) or
|
||||
// If we're looking at the def's own block, just see if it reaches the exit
|
||||
// rank of the block.
|
||||
block = defBlock and
|
||||
locationLiveOnExitFromBlock(useLocation, defBlock) and
|
||||
definitionReachesRank(useLocation, defBlock, defRank, exitRank(useLocation, defBlock))
|
||||
or
|
||||
exists(OldBlock idom |
|
||||
definitionReachesEndOfBlock(useLocation, defBlock, defRank, idom) and
|
||||
noDefinitionsSinceIDominator(useLocation, idom, block)
|
||||
@@ -641,8 +681,9 @@ module DefUse {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate noDefinitionsSinceIDominator(Alias::MemoryLocation useLocation, OldBlock idom,
|
||||
OldBlock block) {
|
||||
private predicate noDefinitionsSinceIDominator(
|
||||
Alias::MemoryLocation useLocation, OldBlock idom, OldBlock block
|
||||
) {
|
||||
Dominance::blockImmediatelyDominates(idom, block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
locationLiveOnExitFromBlock(useLocation, block) and
|
||||
not hasDefinition(useLocation, _, block, _)
|
||||
@@ -655,16 +696,19 @@ module DefUse {
|
||||
* instruction whose result totally overlaps the location.
|
||||
*/
|
||||
predicate locationLiveOnEntryToBlock(Alias::MemoryLocation useLocation, OldBlock block) {
|
||||
definitionHasPhiNode(useLocation, block) or
|
||||
definitionHasPhiNode(useLocation, block)
|
||||
or
|
||||
exists(int firstAccess |
|
||||
hasUse(useLocation, block, firstAccess, _) and
|
||||
firstAccess = min(int offset |
|
||||
hasUse(useLocation, block, offset, _)
|
||||
or
|
||||
hasNonPhiDefinition(useLocation, _, block, offset)
|
||||
)
|
||||
) or
|
||||
(locationLiveOnExitFromBlock(useLocation, block) and not hasNonPhiDefinition(useLocation, _, block, _))
|
||||
hasUse(useLocation, block, offset, _)
|
||||
or
|
||||
hasNonPhiDefinition(useLocation, _, block, offset)
|
||||
)
|
||||
)
|
||||
or
|
||||
locationLiveOnExitFromBlock(useLocation, block) and
|
||||
not hasNonPhiDefinition(useLocation, _, block, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,62 +719,68 @@ module DefUse {
|
||||
locationLiveOnEntryToBlock(useLocation, block.getAFeasibleSuccessor())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate does not include definitions for Phi nodes.
|
||||
*/
|
||||
private predicate hasNonPhiDefinition(Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation,
|
||||
OldBlock block, int offset) {
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate does not include definitions for Phi nodes.
|
||||
*/
|
||||
private predicate hasNonPhiDefinition(
|
||||
Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block, int offset
|
||||
) {
|
||||
exists(OldInstruction def, Overlap overlap, int index |
|
||||
defLocation = Alias::getResultMemoryLocation(def) and
|
||||
block.getInstruction(index) = def and
|
||||
overlap = Alias::getOverlap(defLocation, useLocation) and
|
||||
if overlap instanceof MayPartiallyOverlap then
|
||||
offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
|
||||
else
|
||||
offset = index * 2 // The use will be connected to the definition on the original instruction.
|
||||
if overlap instanceof MayPartiallyOverlap
|
||||
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
|
||||
else offset = index * 2 // The use will be connected to the definition on the original instruction.
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate includes definitions for Phi nodes (at offset -1).
|
||||
*/
|
||||
private predicate hasDefinition(Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block,
|
||||
int offset) {
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate includes definitions for Phi nodes (at offset -1).
|
||||
*/
|
||||
private predicate hasDefinition(
|
||||
Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block, int offset
|
||||
) {
|
||||
(
|
||||
// If there is a Phi node for the use location itself, treat that as a definition at offset -1.
|
||||
offset = -1 and
|
||||
if definitionHasPhiNode(useLocation, block) then (
|
||||
defLocation = useLocation
|
||||
)
|
||||
if definitionHasPhiNode(useLocation, block)
|
||||
then defLocation = useLocation
|
||||
else (
|
||||
definitionHasPhiNode(defLocation, block) and
|
||||
defLocation = useLocation.getVirtualVariable()
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
hasNonPhiDefinition(useLocation, defLocation, block, offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* `rankIndex` is the rank of the definition as computed by `defUseRank()`.
|
||||
*/
|
||||
predicate hasDefinitionAtRank(Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation,
|
||||
OldBlock block, int rankIndex, int offset) {
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* `rankIndex` is the rank of the definition as computed by `defUseRank()`.
|
||||
*/
|
||||
predicate hasDefinitionAtRank(
|
||||
Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block,
|
||||
int rankIndex, int offset
|
||||
) {
|
||||
hasDefinition(useLocation, defLocation, block, offset) and
|
||||
defUseRank(useLocation, block, rankIndex, offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a use of `useLocation` on instruction `use` at offset `offset` in block `block`.
|
||||
*/
|
||||
private predicate hasUse(Alias::MemoryLocation useLocation, OldBlock block, int offset, OldInstruction use) {
|
||||
* Holds if there is a use of `useLocation` on instruction `use` at offset `offset` in block `block`.
|
||||
*/
|
||||
private predicate hasUse(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int offset, OldInstruction use
|
||||
) {
|
||||
exists(int index |
|
||||
block.getInstruction(index) = use and
|
||||
(
|
||||
// A direct use of the location.
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2 or
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
|
||||
or
|
||||
// A `Chi` instruction will include a use of the virtual variable.
|
||||
hasChiNode(useLocation, use) and offset = (index * 2) + 1
|
||||
)
|
||||
@@ -738,10 +788,12 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a use of memory location `useLocation` on instruction `use` in block `block`. `rankIndex` is the
|
||||
* rank of the use use as computed by `defUseRank`.
|
||||
*/
|
||||
predicate hasUseAtRank(Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, OldInstruction use) {
|
||||
* Holds if there is a use of memory location `useLocation` on instruction `use` in block `block`. `rankIndex` is the
|
||||
* rank of the use use as computed by `defUseRank`.
|
||||
*/
|
||||
predicate hasUseAtRank(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, OldInstruction use
|
||||
) {
|
||||
exists(int offset |
|
||||
hasUse(useLocation, block, offset, use) and
|
||||
defUseRank(useLocation, block, rankIndex, offset)
|
||||
@@ -749,12 +801,16 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`, or
|
||||
* a use of `useLocation` at offset `offset` in block `block`. `rankIndex` is the sequence number of the definition
|
||||
* or use within `block`, counting only uses of `useLocation` and definitions that overlap `useLocation`.
|
||||
*/
|
||||
private predicate defUseRank(Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, int offset) {
|
||||
offset = rank[rankIndex](int j | hasDefinition(useLocation, _, block, j) or hasUse(useLocation, block, j, _))
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`, or
|
||||
* a use of `useLocation` at offset `offset` in block `block`. `rankIndex` is the sequence number of the definition
|
||||
* or use within `block`, counting only uses of `useLocation` and definitions that overlap `useLocation`.
|
||||
*/
|
||||
private predicate defUseRank(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, int offset
|
||||
) {
|
||||
offset = rank[rankIndex](int j |
|
||||
hasDefinition(useLocation, _, block, j) or hasUse(useLocation, block, j, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -763,8 +819,10 @@ module DefUse {
|
||||
* and overlaps the use operand with overlap relationship `overlap`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate hasPhiOperandDefinition(Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation,
|
||||
OldBlock phiBlock, OldBlock predBlock, OldBlock defBlock, int defOffset, Overlap overlap) {
|
||||
predicate hasPhiOperandDefinition(
|
||||
Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation, OldBlock phiBlock,
|
||||
OldBlock predBlock, OldBlock defBlock, int defOffset, Overlap overlap
|
||||
) {
|
||||
exists(int defRank |
|
||||
definitionHasPhiNode(useLocation, phiBlock) and
|
||||
predBlock = phiBlock.getAFeasiblePredecessor() and
|
||||
@@ -785,31 +843,34 @@ module DebugSSA {
|
||||
}
|
||||
|
||||
import CachedForDebugging
|
||||
cached private module CachedForDebugging {
|
||||
cached string getTempVariableUniqueId(IRTempVariable var) {
|
||||
|
||||
cached
|
||||
private module CachedForDebugging {
|
||||
cached
|
||||
string getTempVariableUniqueId(IRTempVariable var) {
|
||||
result = getOldTempVariable(var).getUniqueId()
|
||||
}
|
||||
|
||||
cached string getInstructionUniqueId(Instruction instr) {
|
||||
cached
|
||||
string getInstructionUniqueId(Instruction instr) {
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instr) and
|
||||
result = "NonSSA: " + oldInstr.getUniqueId()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(Alias::MemoryLocation location, OldBlock phiBlock, string specificity |
|
||||
instr = Phi(phiBlock, location) and
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
|
||||
if location instanceof Alias::VirtualVariable then (
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " +
|
||||
location.getUniqueId() and
|
||||
if location instanceof Alias::VirtualVariable
|
||||
then
|
||||
// Sort Phi nodes for virtual variables before Phi nodes for member locations.
|
||||
specificity = "g"
|
||||
)
|
||||
else (
|
||||
specificity = "s"
|
||||
)
|
||||
) or
|
||||
(
|
||||
instr = Unreached(_) and
|
||||
result = "Unreached"
|
||||
else specificity = "s"
|
||||
)
|
||||
or
|
||||
instr = Unreached(_) and
|
||||
result = "Unreached"
|
||||
}
|
||||
|
||||
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
|
||||
|
||||
@@ -13,7 +13,8 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
exists(MemoryLocation location |
|
||||
location = getResultMemoryLocation(instruction) and
|
||||
(
|
||||
key = "ResultMemoryLocation" and result = location.toString() or
|
||||
key = "ResultMemoryLocation" and result = location.toString()
|
||||
or
|
||||
key = "ResultVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
)
|
||||
)
|
||||
@@ -21,33 +22,40 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
exists(MemoryLocation location |
|
||||
location = getOperandMemoryLocation(instruction.getAnOperand()) and
|
||||
(
|
||||
key = "OperandMemoryAccess" and result = location.toString() or
|
||||
key = "OperandMemoryAccess" and result = location.toString()
|
||||
or
|
||||
key = "OperandVirtualVariable" and result = location.getVirtualVariable().toString()
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionRank[" + useLocation.toString() + "]" and
|
||||
result = defRank.toString()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock useBlock, int useRank |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, instruction) and
|
||||
key = "UseRank[" + useLocation.toString() + "]" and
|
||||
result = useRank.toString()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, IRBlock defBlock, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, defIndex) and
|
||||
defBlock.getInstruction(defIndex) = instruction and
|
||||
key = "DefinitionReachesUse[" + useLocation.toString() + "]" and
|
||||
result = strictconcat(IRBlock useBlock, int useRank, int useIndex |
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, defBlock, defRank, useBlock, useRank)
|
||||
) |
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", " order by useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, defBlock, defRank, useBlock, useRank)
|
||||
)
|
||||
|
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", "
|
||||
order by
|
||||
useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -57,53 +65,62 @@ class PropertyProvider extends IRPropertyProvider {
|
||||
defIndex = -1 and
|
||||
key = "DefinitionRank(Phi)[" + useLocation.toString() + "]" and
|
||||
result = defRank.toString()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(MemoryLocation useLocation, MemoryLocation defLocation, int defRank, int defIndex |
|
||||
hasDefinitionAtRank(useLocation, defLocation, block, defRank, defIndex) and
|
||||
defIndex = -1 and
|
||||
key = "DefinitionReachesUse(Phi)[" + useLocation.toString() + "]" and
|
||||
result = strictconcat(IRBlock useBlock, int useRank, int useIndex |
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, block, defRank, useBlock, useRank) and
|
||||
exists(getOverlap(defLocation, useLocation))
|
||||
) |
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", " order by useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
) or
|
||||
exists(MemoryLocation useLocation, IRBlock predBlock, IRBlock defBlock, int defIndex, Overlap overlap |
|
||||
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex, overlap) and
|
||||
key = "PhiUse[" + useLocation.toString() + " from " + predBlock.getDisplayIndex().toString() + "]" and
|
||||
result = defBlock.getDisplayIndex().toString() + "_" + defIndex + " (" + overlap.toString() + ")"
|
||||
) or
|
||||
(
|
||||
key = "LiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnEntryToBlock(useLocation, block) |
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
) or
|
||||
(
|
||||
key = "LiveOnExit" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnExitFromBlock(useLocation, block) |
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
) or
|
||||
(
|
||||
key = "DefsLiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnEntryToBlock(defLocation, block) |
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
) or
|
||||
(
|
||||
key = "DefsLiveOnExit" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnExitFromBlock(defLocation, block) |
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
exists(Instruction useInstruction |
|
||||
hasUseAtRank(useLocation, useBlock, useRank, useInstruction) and
|
||||
useBlock.getInstruction(useIndex) = useInstruction and
|
||||
definitionReachesUse(useLocation, block, defRank, useBlock, useRank) and
|
||||
exists(getOverlap(defLocation, useLocation))
|
||||
)
|
||||
|
|
||||
useBlock.getDisplayIndex().toString() + "_" + useIndex, ", "
|
||||
order by
|
||||
useBlock.getDisplayIndex(), useIndex
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
MemoryLocation useLocation, IRBlock predBlock, IRBlock defBlock, int defIndex, Overlap overlap
|
||||
|
|
||||
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex, overlap) and
|
||||
key = "PhiUse[" + useLocation.toString() + " from " + predBlock.getDisplayIndex().toString() +
|
||||
"]" and
|
||||
result = defBlock.getDisplayIndex().toString() + "_" + defIndex + " (" + overlap.toString() +
|
||||
")"
|
||||
)
|
||||
or
|
||||
key = "LiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnEntryToBlock(useLocation, block)
|
||||
|
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
or
|
||||
key = "LiveOnExit" and
|
||||
result = strictconcat(MemoryLocation useLocation |
|
||||
locationLiveOnExitFromBlock(useLocation, block)
|
||||
|
|
||||
useLocation.toString(), ", " order by useLocation.toString()
|
||||
)
|
||||
or
|
||||
key = "DefsLiveOnEntry" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnEntryToBlock(defLocation, block)
|
||||
|
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
or
|
||||
key = "DefsLiveOnExit" and
|
||||
result = strictconcat(MemoryLocation defLocation |
|
||||
definitionLiveOnExitFromBlock(defLocation, block)
|
||||
|
|
||||
defLocation.toString(), ", " order by defLocation.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,31 +6,32 @@ private import semmle.code.cpp.ir.internal.Overlap
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
cached private module Cached {
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
private IRBlock getNewBlock(OldBlock oldBlock) {
|
||||
result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
}
|
||||
|
||||
cached predicate functionHasIR(Function func) {
|
||||
exists(OldIR::IRFunction irFunc |
|
||||
irFunc.getFunction() = func
|
||||
)
|
||||
cached
|
||||
predicate functionHasIR(Function func) {
|
||||
exists(OldIR::IRFunction irFunc | irFunc.getFunction() = func)
|
||||
}
|
||||
|
||||
cached OldInstruction getOldInstruction(Instruction instr) {
|
||||
instr = WrappedInstruction(result)
|
||||
}
|
||||
cached
|
||||
OldInstruction getOldInstruction(Instruction instr) { instr = WrappedInstruction(result) }
|
||||
|
||||
private IRVariable getNewIRVariable(OldIR::IRVariable var) {
|
||||
// This is just a type cast. Both classes derive from the same newtype.
|
||||
result = var
|
||||
}
|
||||
|
||||
cached newtype TInstruction =
|
||||
cached
|
||||
newtype TInstruction =
|
||||
WrappedInstruction(OldInstruction oldInstruction) {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction
|
||||
} or
|
||||
@@ -48,8 +49,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
|
||||
Type type) {
|
||||
cached
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) {
|
||||
exists(OldIR::IRTempVariable var |
|
||||
var.getEnclosingFunction() = func and
|
||||
var.getAST() = ast and
|
||||
@@ -58,13 +59,15 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached predicate hasModeledMemoryResult(Instruction instruction) {
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) {
|
||||
exists(Alias::getResultMemoryLocation(getOldInstruction(instruction))) or
|
||||
instruction instanceof PhiInstruction or // Phis always have modeled results
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
instruction instanceof PhiInstruction or // Phis always have modeled results
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
@@ -73,16 +76,22 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getMemoryOperandDefinition(Instruction instruction, MemoryOperandTag tag, Overlap overlap) {
|
||||
cached
|
||||
Instruction getMemoryOperandDefinition(
|
||||
Instruction instruction, MemoryOperandTag tag, Overlap overlap
|
||||
) {
|
||||
exists(OldInstruction oldInstruction, OldIR::NonPhiMemoryOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
(
|
||||
(
|
||||
if exists(Alias::getOperandMemoryLocation(oldOperand)) then (
|
||||
exists(OldBlock useBlock, int useRank, Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation,
|
||||
OldBlock defBlock, int defRank, int defOffset |
|
||||
if exists(Alias::getOperandMemoryLocation(oldOperand))
|
||||
then
|
||||
exists(
|
||||
OldBlock useBlock, int useRank, Alias::MemoryLocation useLocation,
|
||||
Alias::MemoryLocation defLocation, OldBlock defBlock, int defRank, int defOffset
|
||||
|
|
||||
useLocation = Alias::getOperandMemoryLocation(oldOperand) and
|
||||
hasDefinitionAtRank(useLocation, defLocation, defBlock, defRank, defOffset) and
|
||||
hasUseAtRank(useLocation, useBlock, useRank, oldInstruction) and
|
||||
@@ -90,12 +99,12 @@ cached private module Cached {
|
||||
overlap = Alias::getOverlap(defLocation, useLocation) and
|
||||
result = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation)
|
||||
)
|
||||
)
|
||||
else (
|
||||
result = instruction.getEnclosingIRFunction().getUnmodeledDefinitionInstruction() and
|
||||
overlap instanceof MustTotallyOverlap
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
// Connect any definitions that are not being modeled in SSA to the
|
||||
// `UnmodeledUse` instruction.
|
||||
exists(OldInstruction oldDefinition |
|
||||
@@ -107,7 +116,8 @@ cached private module Cached {
|
||||
overlap instanceof MustTotallyOverlap
|
||||
)
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
instruction = Chi(getOldInstruction(result)) and
|
||||
tag instanceof ChiPartialOperandTag and
|
||||
overlap instanceof MustExactlyOverlap
|
||||
@@ -124,7 +134,8 @@ cached private module Cached {
|
||||
overlap instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
cached Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
cached
|
||||
Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::TypedOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
@@ -133,7 +144,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
|
||||
cached
|
||||
int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::SideEffectOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instr) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
@@ -144,20 +156,28 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPhiOperandDefinition(PhiInstruction instr,
|
||||
IRBlock newPredecessorBlock, Overlap overlap) {
|
||||
exists(Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation, OldBlock phiBlock, OldBlock predBlock,
|
||||
OldBlock defBlock, int defOffset |
|
||||
hasPhiOperandDefinition(defLocation, useLocation, phiBlock, predBlock, defBlock, defOffset, overlap) and
|
||||
cached
|
||||
Instruction getPhiOperandDefinition(
|
||||
PhiInstruction instr, IRBlock newPredecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(
|
||||
Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation, OldBlock phiBlock,
|
||||
OldBlock predBlock, OldBlock defBlock, int defOffset
|
||||
|
|
||||
hasPhiOperandDefinition(defLocation, useLocation, phiBlock, predBlock, defBlock, defOffset,
|
||||
overlap) and
|
||||
instr = Phi(phiBlock, useLocation) and
|
||||
newPredecessorBlock = getNewBlock(predBlock) and
|
||||
result = getDefinitionOrChiInstruction(defBlock, defOffset, defLocation)
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
|
||||
exists(Alias::VirtualVariable vvar, OldInstruction oldInstr, Alias::MemoryLocation defLocation, OldBlock defBlock,
|
||||
int defRank, int defOffset, OldBlock useBlock, int useRank |
|
||||
cached
|
||||
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
|
||||
exists(
|
||||
Alias::VirtualVariable vvar, OldInstruction oldInstr, Alias::MemoryLocation defLocation,
|
||||
OldBlock defBlock, int defRank, int defOffset, OldBlock useBlock, int useRank
|
||||
|
|
||||
chiInstr = Chi(oldInstr) and
|
||||
vvar = Alias::getResultMemoryLocation(oldInstr).getVirtualVariable() and
|
||||
hasDefinitionAtRank(vvar, defLocation, defBlock, defRank, defOffset) and
|
||||
@@ -167,28 +187,32 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
|
||||
cached
|
||||
Instruction getPhiInstructionBlockStart(PhiInstruction instr) {
|
||||
exists(OldBlock oldBlock |
|
||||
instr = Phi(oldBlock, _) and
|
||||
result = getNewInstruction(oldBlock.getFirstInstruction())
|
||||
)
|
||||
}
|
||||
|
||||
cached Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
cached
|
||||
Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getConvertedResultExpression()
|
||||
}
|
||||
|
||||
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
cached
|
||||
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
|
||||
* that node is its successor in the new successor relation, and the Chi node's successors are
|
||||
* the new instructions generated from the successors of the old instruction
|
||||
*/
|
||||
cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
if(hasChiNode(_, getOldInstruction(instruction)))
|
||||
cached
|
||||
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
if hasChiNode(_, getOldInstruction(instruction))
|
||||
then
|
||||
result = Chi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -196,14 +220,12 @@ cached private module Cached {
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then (
|
||||
result = Unreached(instruction.getEnclosingFunction())
|
||||
)
|
||||
else (
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = Unreached(instruction.getEnclosingFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = Chi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
@@ -211,7 +233,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
cached
|
||||
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
not Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) and
|
||||
// There is only one case for the translation into `result` because the
|
||||
@@ -228,7 +251,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Locatable getInstructionAST(Instruction instruction) {
|
||||
cached
|
||||
Locatable getInstructionAST(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction)
|
||||
or
|
||||
@@ -245,13 +269,12 @@ cached private module Cached {
|
||||
instruction = Unreached(result)
|
||||
}
|
||||
|
||||
cached predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
cached
|
||||
predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction) and
|
||||
type = oldInstruction.getResultType() and
|
||||
if oldInstruction.isGLValue()
|
||||
then isGLValue = true
|
||||
else isGLValue = false
|
||||
if oldInstruction.isGLValue() then isGLValue = true else isGLValue = false
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction, Alias::VirtualVariable vvar |
|
||||
@@ -272,7 +295,8 @@ cached private module Cached {
|
||||
isGLValue = false
|
||||
}
|
||||
|
||||
cached Opcode getInstructionOpcode(Instruction instruction) {
|
||||
cached
|
||||
Opcode getInstructionOpcode(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction) and
|
||||
result = oldInstruction.getOpcode()
|
||||
@@ -288,7 +312,8 @@ cached private module Cached {
|
||||
result instanceof Opcode::Unreached
|
||||
}
|
||||
|
||||
cached IRFunction getInstructionEnclosingIRFunction(Instruction instruction) {
|
||||
cached
|
||||
IRFunction getInstructionEnclosingIRFunction(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = WrappedInstruction(oldInstruction)
|
||||
or
|
||||
@@ -305,46 +330,59 @@ cached private module Cached {
|
||||
instruction = Unreached(result.getFunction())
|
||||
}
|
||||
|
||||
cached IRVariable getInstructionVariable(Instruction instruction) {
|
||||
result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable())
|
||||
cached
|
||||
IRVariable getInstructionVariable(Instruction instruction) {
|
||||
result = getNewIRVariable(getOldInstruction(instruction)
|
||||
.(OldIR::VariableInstruction)
|
||||
.getVariable())
|
||||
}
|
||||
|
||||
cached Field getInstructionField(Instruction instruction) {
|
||||
cached
|
||||
Field getInstructionField(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField()
|
||||
}
|
||||
|
||||
cached Function getInstructionFunction(Instruction instruction) {
|
||||
cached
|
||||
Function getInstructionFunction(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
cached string getInstructionConstantValue(Instruction instruction) {
|
||||
cached
|
||||
string getInstructionConstantValue(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
|
||||
}
|
||||
|
||||
cached StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
cached
|
||||
StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::BuiltInOperationInstruction).getBuiltInOperation()
|
||||
cached
|
||||
BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
.(OldIR::BuiltInOperationInstruction)
|
||||
.getBuiltInOperation()
|
||||
}
|
||||
|
||||
cached Type getInstructionExceptionType(Instruction instruction) {
|
||||
cached
|
||||
Type getInstructionExceptionType(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType()
|
||||
}
|
||||
|
||||
cached int getInstructionElementSize(Instruction instruction) {
|
||||
cached
|
||||
int getInstructionElementSize(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize()
|
||||
}
|
||||
|
||||
cached int getInstructionResultSize(Instruction instruction) {
|
||||
cached
|
||||
int getInstructionResultSize(Instruction instruction) {
|
||||
// Only return a result for instructions that needed an explicit result size.
|
||||
instruction.getResultType() instanceof UnknownType and
|
||||
result = getOldInstruction(instruction).getResultSize()
|
||||
}
|
||||
|
||||
cached predicate getInstructionInheritance(Instruction instruction, Class baseClass,
|
||||
Class derivedClass) {
|
||||
cached
|
||||
predicate getInstructionInheritance(Instruction instruction, Class baseClass, Class derivedClass) {
|
||||
exists(OldIR::InheritanceConversionInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instruction) and
|
||||
baseClass = oldInstr.getBaseClass() and
|
||||
@@ -352,7 +390,8 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
cached
|
||||
Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
exists(OldIR::SideEffectInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
|
||||
@@ -365,9 +404,7 @@ cached private module Cached {
|
||||
}
|
||||
}
|
||||
|
||||
private Instruction getNewInstruction(OldInstruction instr) {
|
||||
getOldInstruction(result) = instr
|
||||
}
|
||||
private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(result) = instr }
|
||||
|
||||
/**
|
||||
* Holds if instruction `def` needs to have a `Chi` instruction inserted after it, to account for a partial definition
|
||||
@@ -413,16 +450,18 @@ private module PhiInsertion {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the memory location `defLocation` has a definition in block `block`, either because of an existing
|
||||
* instruction, a `Phi` node, or a `Chi` node.
|
||||
*/
|
||||
* Holds if the memory location `defLocation` has a definition in block `block`, either because of an existing
|
||||
* instruction, a `Phi` node, or a `Chi` node.
|
||||
*/
|
||||
private predicate definitionHasDefinitionInBlock(Alias::MemoryLocation defLocation, OldBlock block) {
|
||||
definitionHasPhiNode(defLocation, block) or
|
||||
definitionHasPhiNode(defLocation, block)
|
||||
or
|
||||
exists(OldInstruction def, Alias::MemoryLocation resultLocation |
|
||||
def.getBlock() = block and
|
||||
resultLocation = Alias::getResultMemoryLocation(def) and
|
||||
(
|
||||
defLocation = resultLocation or
|
||||
defLocation = resultLocation
|
||||
or
|
||||
// For a virtual variable, any definition of a member location will either generate a `Chi` node that defines
|
||||
// the virtual variable, or will totally overlap the virtual variable. Either way, treat this as a definition of
|
||||
// the virtual variable.
|
||||
@@ -438,16 +477,17 @@ private module PhiInsertion {
|
||||
private predicate definitionHasUse(Alias::MemoryLocation defLocation, OldBlock block, int index) {
|
||||
exists(OldInstruction use |
|
||||
block.getInstruction(index) = use and
|
||||
if defLocation instanceof Alias::VirtualVariable then (
|
||||
if defLocation instanceof Alias::VirtualVariable
|
||||
then (
|
||||
exists(Alias::MemoryLocation useLocation |
|
||||
// For a virtual variable, any use of a location that is a member of the virtual variable counts as a use.
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
|
||||
defLocation = useLocation.getVirtualVariable()
|
||||
) or
|
||||
// For a virtual variable, any use of a location that is a member of the virtual variable counts as a use.
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
|
||||
defLocation = useLocation.getVirtualVariable()
|
||||
)
|
||||
or
|
||||
// A `Chi` instruction consumes the enclosing virtual variable of its use location.
|
||||
hasChiNode(defLocation, use)
|
||||
)
|
||||
else (
|
||||
) else (
|
||||
// For other locations, only an exactly-overlapping use of the same location counts as a use.
|
||||
defLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
|
||||
Alias::getOverlap(defLocation, defLocation) instanceof MustExactlyOverlap
|
||||
@@ -460,11 +500,14 @@ private module PhiInsertion {
|
||||
* there is a definition that would prevent a previous definition of `defLocation` from being consumed as the operand
|
||||
* of a `Phi` node that occurs after the redefinition.
|
||||
*/
|
||||
private predicate definitionHasRedefinition(Alias::MemoryLocation defLocation, OldBlock block, int index) {
|
||||
private predicate definitionHasRedefinition(
|
||||
Alias::MemoryLocation defLocation, OldBlock block, int index
|
||||
) {
|
||||
exists(OldInstruction redef, Alias::MemoryLocation redefLocation |
|
||||
block.getInstruction(index) = redef and
|
||||
redefLocation = Alias::getResultMemoryLocation(redef) and
|
||||
if defLocation instanceof Alias::VirtualVariable then (
|
||||
if defLocation instanceof Alias::VirtualVariable
|
||||
then
|
||||
// For a virtual variable, the definition may be consumed by any use of a location that is a member of the
|
||||
// virtual variable. Thus, the definition is live until a subsequent redefinition of the entire virtual
|
||||
// variable.
|
||||
@@ -472,20 +515,18 @@ private module PhiInsertion {
|
||||
overlap = Alias::getOverlap(redefLocation, defLocation) and
|
||||
not overlap instanceof MayPartiallyOverlap
|
||||
)
|
||||
)
|
||||
else (
|
||||
else
|
||||
// For other locations, the definition may only be consumed by an exactly-overlapping use of the same location.
|
||||
// Thus, the definition is live until a subsequent definition of any location that may overlap the original
|
||||
// definition location.
|
||||
exists(Alias::getOverlap(redefLocation, defLocation))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the definition `defLocation` is live on entry to block `block`. The definition is live if there is at
|
||||
* least one use of that definition before any intervening instruction that redefines the definition location.
|
||||
*/
|
||||
* Holds if the definition `defLocation` is live on entry to block `block`. The definition is live if there is at
|
||||
* least one use of that definition before any intervening instruction that redefines the definition location.
|
||||
*/
|
||||
predicate definitionLiveOnEntryToBlock(Alias::MemoryLocation defLocation, OldBlock block) {
|
||||
exists(int firstAccess |
|
||||
definitionHasUse(defLocation, block, firstAccess) and
|
||||
@@ -496,7 +537,8 @@ private module PhiInsertion {
|
||||
)
|
||||
)
|
||||
or
|
||||
(definitionLiveOnExitFromBlock(defLocation, block) and not definitionHasRedefinition(defLocation, block, _))
|
||||
definitionLiveOnExitFromBlock(defLocation, block) and
|
||||
not definitionHasRedefinition(defLocation, block, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,7 +558,7 @@ private import DefUse
|
||||
* computed separately for each unique use `MemoryLocation`. An instruction is treated as a definition of a use location
|
||||
* if the defined location overlaps the use location in any way. Thus, a single instruction may serve as a definition
|
||||
* for multiple use locations, since a single definition location may overlap many use locations.
|
||||
*
|
||||
*
|
||||
* Definitions and uses are identified by a block and an integer "offset". An offset of -1 indicates the definition
|
||||
* from a `Phi` instruction at the beginning of the block. An offset of 2*i indicates a definition or use on the
|
||||
* instruction at index `i` in the block. An offset of 2*i+1 indicates a definition or use on the `Chi` instruction that
|
||||
@@ -532,47 +574,46 @@ module DefUse {
|
||||
/**
|
||||
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
|
||||
*/
|
||||
pragma[inline]
|
||||
bindingset[defOffset, defLocation]
|
||||
Instruction getDefinitionOrChiInstruction(OldBlock defBlock, int defOffset,
|
||||
Alias::MemoryLocation defLocation) {
|
||||
(
|
||||
defOffset >= 0 and
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = defBlock.getInstruction(defOffset / 2) and
|
||||
if (defOffset % 2) > 0 then (
|
||||
// An odd offset corresponds to the `Chi` instruction.
|
||||
result = Chi(oldInstr)
|
||||
)
|
||||
else (
|
||||
// An even offset corresponds to the original instruction.
|
||||
result = getNewInstruction(oldInstr)
|
||||
)
|
||||
)
|
||||
) or
|
||||
(
|
||||
defOffset < 0 and
|
||||
result = Phi(defBlock, defLocation)
|
||||
pragma[inline]
|
||||
Instruction getDefinitionOrChiInstruction(
|
||||
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation
|
||||
) {
|
||||
defOffset >= 0 and
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = defBlock.getInstruction(defOffset / 2) and
|
||||
if (defOffset % 2) > 0
|
||||
then
|
||||
// An odd offset corresponds to the `Chi` instruction.
|
||||
result = Chi(oldInstr)
|
||||
else
|
||||
// An even offset corresponds to the original instruction.
|
||||
result = getNewInstruction(oldInstr)
|
||||
)
|
||||
or
|
||||
defOffset < 0 and
|
||||
result = Phi(defBlock, defLocation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
*/
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
*/
|
||||
private int exitRank(Alias::MemoryLocation useLocation, OldBlock block) {
|
||||
result = max(int rankIndex | defUseRank(useLocation, block, rankIndex, _)) + 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`, where `defBlock` and
|
||||
* `useBlock` are the same block.
|
||||
*/
|
||||
private predicate definitionReachesUseWithinBlock(Alias::MemoryLocation useLocation, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`, where `defBlock` and
|
||||
* `useBlock` are the same block.
|
||||
*/
|
||||
private predicate definitionReachesUseWithinBlock(
|
||||
Alias::MemoryLocation useLocation, OldBlock defBlock, int defRank, OldBlock useBlock,
|
||||
int useRank
|
||||
) {
|
||||
defBlock = useBlock and
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, _) and
|
||||
hasUseAtRank(useLocation, useBlock, useRank, _) and
|
||||
@@ -580,59 +621,58 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesUse(Alias::MemoryLocation useLocation, OldBlock defBlock,
|
||||
int defRank, OldBlock useBlock, int useRank) {
|
||||
* Holds if a definition that overlaps `useLocation` at (`defBlock`, `defRank`) reaches the use of `useLocation` at
|
||||
* (`useBlock`, `useRank`) without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesUse(
|
||||
Alias::MemoryLocation useLocation, OldBlock defBlock, int defRank, OldBlock useBlock,
|
||||
int useRank
|
||||
) {
|
||||
hasUseAtRank(useLocation, useBlock, useRank, _) and
|
||||
(
|
||||
definitionReachesUseWithinBlock(useLocation, defBlock, defRank, useBlock,
|
||||
useRank) or
|
||||
(
|
||||
definitionReachesEndOfBlock(useLocation, defBlock, defRank,
|
||||
useBlock.getAFeasiblePredecessor()) and
|
||||
not definitionReachesUseWithinBlock(useLocation, useBlock, _, useBlock, useRank)
|
||||
)
|
||||
definitionReachesUseWithinBlock(useLocation, defBlock, defRank, useBlock, useRank)
|
||||
or
|
||||
definitionReachesEndOfBlock(useLocation, defBlock, defRank, useBlock.getAFeasiblePredecessor()) and
|
||||
not definitionReachesUseWithinBlock(useLocation, useBlock, _, useBlock, useRank)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the definition that overlaps `useLocation` at `(block, defRank)` reaches the rank
|
||||
* index `reachesRank` in block `block`.
|
||||
*/
|
||||
private predicate definitionReachesRank(Alias::MemoryLocation useLocation, OldBlock block, int defRank,
|
||||
int reachesRank) {
|
||||
* Holds if the definition that overlaps `useLocation` at `(block, defRank)` reaches the rank
|
||||
* index `reachesRank` in block `block`.
|
||||
*/
|
||||
private predicate definitionReachesRank(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int defRank, int reachesRank
|
||||
) {
|
||||
hasDefinitionAtRank(useLocation, _, block, defRank, _) and
|
||||
reachesRank <= exitRank(useLocation, block) and // Without this, the predicate would be infinite.
|
||||
reachesRank <= exitRank(useLocation, block) and // Without this, the predicate would be infinite.
|
||||
(
|
||||
// The def always reaches the next use, even if there is also a def on the
|
||||
// use instruction.
|
||||
reachesRank = defRank + 1 or
|
||||
(
|
||||
// If the def reached the previous rank, it also reaches the current rank,
|
||||
// unless there was another def at the previous rank.
|
||||
definitionReachesRank(useLocation, block, defRank, reachesRank - 1) and
|
||||
not hasDefinitionAtRank(useLocation, _, block, reachesRank - 1, _)
|
||||
)
|
||||
reachesRank = defRank + 1
|
||||
or
|
||||
// If the def reached the previous rank, it also reaches the current rank,
|
||||
// unless there was another def at the previous rank.
|
||||
definitionReachesRank(useLocation, block, defRank, reachesRank - 1) and
|
||||
not hasDefinitionAtRank(useLocation, _, block, reachesRank - 1, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the definition that overlaps `useLocation` at `(defBlock, defRank)` reaches the end of
|
||||
* block `block` without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesEndOfBlock(Alias::MemoryLocation useLocation, OldBlock defBlock,
|
||||
int defRank, OldBlock block) {
|
||||
* Holds if the definition that overlaps `useLocation` at `(defBlock, defRank)` reaches the end of
|
||||
* block `block` without any intervening definitions that overlap `useLocation`.
|
||||
*/
|
||||
predicate definitionReachesEndOfBlock(
|
||||
Alias::MemoryLocation useLocation, OldBlock defBlock, int defRank, OldBlock block
|
||||
) {
|
||||
hasDefinitionAtRank(useLocation, _, defBlock, defRank, _) and
|
||||
(
|
||||
(
|
||||
// If we're looking at the def's own block, just see if it reaches the exit
|
||||
// rank of the block.
|
||||
block = defBlock and
|
||||
locationLiveOnExitFromBlock(useLocation, defBlock) and
|
||||
definitionReachesRank(useLocation, defBlock, defRank, exitRank(useLocation, defBlock))
|
||||
) or
|
||||
// If we're looking at the def's own block, just see if it reaches the exit
|
||||
// rank of the block.
|
||||
block = defBlock and
|
||||
locationLiveOnExitFromBlock(useLocation, defBlock) and
|
||||
definitionReachesRank(useLocation, defBlock, defRank, exitRank(useLocation, defBlock))
|
||||
or
|
||||
exists(OldBlock idom |
|
||||
definitionReachesEndOfBlock(useLocation, defBlock, defRank, idom) and
|
||||
noDefinitionsSinceIDominator(useLocation, idom, block)
|
||||
@@ -641,8 +681,9 @@ module DefUse {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate noDefinitionsSinceIDominator(Alias::MemoryLocation useLocation, OldBlock idom,
|
||||
OldBlock block) {
|
||||
private predicate noDefinitionsSinceIDominator(
|
||||
Alias::MemoryLocation useLocation, OldBlock idom, OldBlock block
|
||||
) {
|
||||
Dominance::blockImmediatelyDominates(idom, block) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
locationLiveOnExitFromBlock(useLocation, block) and
|
||||
not hasDefinition(useLocation, _, block, _)
|
||||
@@ -655,16 +696,19 @@ module DefUse {
|
||||
* instruction whose result totally overlaps the location.
|
||||
*/
|
||||
predicate locationLiveOnEntryToBlock(Alias::MemoryLocation useLocation, OldBlock block) {
|
||||
definitionHasPhiNode(useLocation, block) or
|
||||
definitionHasPhiNode(useLocation, block)
|
||||
or
|
||||
exists(int firstAccess |
|
||||
hasUse(useLocation, block, firstAccess, _) and
|
||||
firstAccess = min(int offset |
|
||||
hasUse(useLocation, block, offset, _)
|
||||
or
|
||||
hasNonPhiDefinition(useLocation, _, block, offset)
|
||||
)
|
||||
) or
|
||||
(locationLiveOnExitFromBlock(useLocation, block) and not hasNonPhiDefinition(useLocation, _, block, _))
|
||||
hasUse(useLocation, block, offset, _)
|
||||
or
|
||||
hasNonPhiDefinition(useLocation, _, block, offset)
|
||||
)
|
||||
)
|
||||
or
|
||||
locationLiveOnExitFromBlock(useLocation, block) and
|
||||
not hasNonPhiDefinition(useLocation, _, block, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,62 +719,68 @@ module DefUse {
|
||||
locationLiveOnEntryToBlock(useLocation, block.getAFeasibleSuccessor())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate does not include definitions for Phi nodes.
|
||||
*/
|
||||
private predicate hasNonPhiDefinition(Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation,
|
||||
OldBlock block, int offset) {
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate does not include definitions for Phi nodes.
|
||||
*/
|
||||
private predicate hasNonPhiDefinition(
|
||||
Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block, int offset
|
||||
) {
|
||||
exists(OldInstruction def, Overlap overlap, int index |
|
||||
defLocation = Alias::getResultMemoryLocation(def) and
|
||||
block.getInstruction(index) = def and
|
||||
overlap = Alias::getOverlap(defLocation, useLocation) and
|
||||
if overlap instanceof MayPartiallyOverlap then
|
||||
offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
|
||||
else
|
||||
offset = index * 2 // The use will be connected to the definition on the original instruction.
|
||||
if overlap instanceof MayPartiallyOverlap
|
||||
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
|
||||
else offset = index * 2 // The use will be connected to the definition on the original instruction.
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate includes definitions for Phi nodes (at offset -1).
|
||||
*/
|
||||
private predicate hasDefinition(Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block,
|
||||
int offset) {
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* This predicate includes definitions for Phi nodes (at offset -1).
|
||||
*/
|
||||
private predicate hasDefinition(
|
||||
Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block, int offset
|
||||
) {
|
||||
(
|
||||
// If there is a Phi node for the use location itself, treat that as a definition at offset -1.
|
||||
offset = -1 and
|
||||
if definitionHasPhiNode(useLocation, block) then (
|
||||
defLocation = useLocation
|
||||
)
|
||||
if definitionHasPhiNode(useLocation, block)
|
||||
then defLocation = useLocation
|
||||
else (
|
||||
definitionHasPhiNode(defLocation, block) and
|
||||
defLocation = useLocation.getVirtualVariable()
|
||||
)
|
||||
) or
|
||||
)
|
||||
or
|
||||
hasNonPhiDefinition(useLocation, defLocation, block, offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* `rankIndex` is the rank of the definition as computed by `defUseRank()`.
|
||||
*/
|
||||
predicate hasDefinitionAtRank(Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation,
|
||||
OldBlock block, int rankIndex, int offset) {
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`.
|
||||
* `rankIndex` is the rank of the definition as computed by `defUseRank()`.
|
||||
*/
|
||||
predicate hasDefinitionAtRank(
|
||||
Alias::MemoryLocation useLocation, Alias::MemoryLocation defLocation, OldBlock block,
|
||||
int rankIndex, int offset
|
||||
) {
|
||||
hasDefinition(useLocation, defLocation, block, offset) and
|
||||
defUseRank(useLocation, block, rankIndex, offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a use of `useLocation` on instruction `use` at offset `offset` in block `block`.
|
||||
*/
|
||||
private predicate hasUse(Alias::MemoryLocation useLocation, OldBlock block, int offset, OldInstruction use) {
|
||||
* Holds if there is a use of `useLocation` on instruction `use` at offset `offset` in block `block`.
|
||||
*/
|
||||
private predicate hasUse(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int offset, OldInstruction use
|
||||
) {
|
||||
exists(int index |
|
||||
block.getInstruction(index) = use and
|
||||
(
|
||||
// A direct use of the location.
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2 or
|
||||
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
|
||||
or
|
||||
// A `Chi` instruction will include a use of the virtual variable.
|
||||
hasChiNode(useLocation, use) and offset = (index * 2) + 1
|
||||
)
|
||||
@@ -738,10 +788,12 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a use of memory location `useLocation` on instruction `use` in block `block`. `rankIndex` is the
|
||||
* rank of the use use as computed by `defUseRank`.
|
||||
*/
|
||||
predicate hasUseAtRank(Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, OldInstruction use) {
|
||||
* Holds if there is a use of memory location `useLocation` on instruction `use` in block `block`. `rankIndex` is the
|
||||
* rank of the use use as computed by `defUseRank`.
|
||||
*/
|
||||
predicate hasUseAtRank(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, OldInstruction use
|
||||
) {
|
||||
exists(int offset |
|
||||
hasUse(useLocation, block, offset, use) and
|
||||
defUseRank(useLocation, block, rankIndex, offset)
|
||||
@@ -749,12 +801,16 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`, or
|
||||
* a use of `useLocation` at offset `offset` in block `block`. `rankIndex` is the sequence number of the definition
|
||||
* or use within `block`, counting only uses of `useLocation` and definitions that overlap `useLocation`.
|
||||
*/
|
||||
private predicate defUseRank(Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, int offset) {
|
||||
offset = rank[rankIndex](int j | hasDefinition(useLocation, _, block, j) or hasUse(useLocation, block, j, _))
|
||||
* Holds if there is a definition at offset `offset` in block `block` that overlaps memory location `useLocation`, or
|
||||
* a use of `useLocation` at offset `offset` in block `block`. `rankIndex` is the sequence number of the definition
|
||||
* or use within `block`, counting only uses of `useLocation` and definitions that overlap `useLocation`.
|
||||
*/
|
||||
private predicate defUseRank(
|
||||
Alias::MemoryLocation useLocation, OldBlock block, int rankIndex, int offset
|
||||
) {
|
||||
offset = rank[rankIndex](int j |
|
||||
hasDefinition(useLocation, _, block, j) or hasUse(useLocation, block, j, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -763,8 +819,10 @@ module DefUse {
|
||||
* and overlaps the use operand with overlap relationship `overlap`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate hasPhiOperandDefinition(Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation,
|
||||
OldBlock phiBlock, OldBlock predBlock, OldBlock defBlock, int defOffset, Overlap overlap) {
|
||||
predicate hasPhiOperandDefinition(
|
||||
Alias::MemoryLocation defLocation, Alias::MemoryLocation useLocation, OldBlock phiBlock,
|
||||
OldBlock predBlock, OldBlock defBlock, int defOffset, Overlap overlap
|
||||
) {
|
||||
exists(int defRank |
|
||||
definitionHasPhiNode(useLocation, phiBlock) and
|
||||
predBlock = phiBlock.getAFeasiblePredecessor() and
|
||||
@@ -785,31 +843,34 @@ module DebugSSA {
|
||||
}
|
||||
|
||||
import CachedForDebugging
|
||||
cached private module CachedForDebugging {
|
||||
cached string getTempVariableUniqueId(IRTempVariable var) {
|
||||
|
||||
cached
|
||||
private module CachedForDebugging {
|
||||
cached
|
||||
string getTempVariableUniqueId(IRTempVariable var) {
|
||||
result = getOldTempVariable(var).getUniqueId()
|
||||
}
|
||||
|
||||
cached string getInstructionUniqueId(Instruction instr) {
|
||||
cached
|
||||
string getInstructionUniqueId(Instruction instr) {
|
||||
exists(OldInstruction oldInstr |
|
||||
oldInstr = getOldInstruction(instr) and
|
||||
result = "NonSSA: " + oldInstr.getUniqueId()
|
||||
) or
|
||||
)
|
||||
or
|
||||
exists(Alias::MemoryLocation location, OldBlock phiBlock, string specificity |
|
||||
instr = Phi(phiBlock, location) and
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
|
||||
if location instanceof Alias::VirtualVariable then (
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " +
|
||||
location.getUniqueId() and
|
||||
if location instanceof Alias::VirtualVariable
|
||||
then
|
||||
// Sort Phi nodes for virtual variables before Phi nodes for member locations.
|
||||
specificity = "g"
|
||||
)
|
||||
else (
|
||||
specificity = "s"
|
||||
)
|
||||
) or
|
||||
(
|
||||
instr = Unreached(_) and
|
||||
result = "Unreached"
|
||||
else specificity = "s"
|
||||
)
|
||||
or
|
||||
instr = Unreached(_) and
|
||||
result = "Unreached"
|
||||
}
|
||||
|
||||
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
|
||||
|
||||
@@ -7,12 +7,16 @@ private import semmle.code.cpp.ir.internal.Overlap
|
||||
|
||||
private class IntValue = Ints::IntValue;
|
||||
|
||||
private predicate hasResultMemoryAccess(Instruction instr, IRVariable var, Type type, IntValue bitOffset) {
|
||||
private predicate hasResultMemoryAccess(
|
||||
Instruction instr, IRVariable var, Type type, IntValue bitOffset
|
||||
) {
|
||||
resultPointsTo(instr.getResultAddressOperand().getAnyDef(), var, bitOffset) and
|
||||
type = instr.getResultType()
|
||||
}
|
||||
|
||||
private predicate hasOperandMemoryAccess(MemoryOperand operand, IRVariable var, Type type, IntValue bitOffset) {
|
||||
private predicate hasOperandMemoryAccess(
|
||||
MemoryOperand operand, IRVariable var, Type type, IntValue bitOffset
|
||||
) {
|
||||
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, bitOffset) and
|
||||
type = operand.getType()
|
||||
}
|
||||
@@ -27,56 +31,40 @@ private predicate isVariableModeled(IRVariable var) {
|
||||
// There's no need to check for the right size. An `IRVariable` never has an `UnknownType`, so the test for
|
||||
// `type = var.getType()` is sufficient.
|
||||
forall(Instruction instr, Type type, IntValue bitOffset |
|
||||
hasResultMemoryAccess(instr, var, type, bitOffset) |
|
||||
hasResultMemoryAccess(instr, var, type, bitOffset)
|
||||
|
|
||||
bitOffset = 0 and
|
||||
type = var.getType()
|
||||
) and
|
||||
forall(MemoryOperand operand, Type type, IntValue bitOffset |
|
||||
hasOperandMemoryAccess(operand, var, type, bitOffset) |
|
||||
hasOperandMemoryAccess(operand, var, type, bitOffset)
|
||||
|
|
||||
bitOffset = 0 and
|
||||
type = var.getType()
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TMemoryLocation =
|
||||
MkMemoryLocation(IRVariable var) {
|
||||
isVariableModeled(var)
|
||||
}
|
||||
private newtype TMemoryLocation = MkMemoryLocation(IRVariable var) { isVariableModeled(var) }
|
||||
|
||||
private MemoryLocation getMemoryLocation(IRVariable var) {
|
||||
result.getIRVariable() = var
|
||||
}
|
||||
private MemoryLocation getMemoryLocation(IRVariable var) { result.getIRVariable() = var }
|
||||
|
||||
class MemoryLocation extends TMemoryLocation {
|
||||
IRVariable var;
|
||||
|
||||
MemoryLocation() {
|
||||
this = MkMemoryLocation(var)
|
||||
}
|
||||
MemoryLocation() { this = MkMemoryLocation(var) }
|
||||
|
||||
final string toString() {
|
||||
result = var.toString()
|
||||
}
|
||||
final string toString() { result = var.toString() }
|
||||
|
||||
final IRVariable getIRVariable() {
|
||||
result = var
|
||||
}
|
||||
final IRVariable getIRVariable() { result = var }
|
||||
|
||||
final VirtualVariable getVirtualVariable() {
|
||||
result = this
|
||||
}
|
||||
final VirtualVariable getVirtualVariable() { result = this }
|
||||
|
||||
final Type getType() {
|
||||
result = var.getType()
|
||||
}
|
||||
final Type getType() { result = var.getType() }
|
||||
|
||||
final string getUniqueId() {
|
||||
result = var.getUniqueId()
|
||||
}
|
||||
final string getUniqueId() { result = var.getUniqueId() }
|
||||
}
|
||||
|
||||
class VirtualVariable extends MemoryLocation {
|
||||
}
|
||||
class VirtualVariable extends MemoryLocation { }
|
||||
|
||||
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
def = use and result instanceof MustExactlyOverlap
|
||||
|
||||
@@ -330,13 +330,7 @@ GlobalOrNamespaceVariable globalVarFromId(string id) {
|
||||
* A variable that has any kind of upper-bound check anywhere in the program
|
||||
*/
|
||||
private predicate hasUpperBoundsCheck(Variable var) {
|
||||
exists(BinaryOperation oper, VariableAccess access |
|
||||
(
|
||||
oper.getOperator() = "<" or
|
||||
oper.getOperator() = "<=" or
|
||||
oper.getOperator() = ">" or
|
||||
oper.getOperator() = ">="
|
||||
) and
|
||||
exists(RelationalOperation oper, VariableAccess access |
|
||||
oper.getLeftOperand() = access and
|
||||
access.getTarget() = var and
|
||||
// Comparing to 0 is not an upper bound check
|
||||
|
||||
@@ -213,6 +213,253 @@ edges
|
||||
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | {...} [a] |
|
||||
| struct_init.c:31:8:31:12 | outer [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB [a] |
|
||||
| struct_init.c:31:14:31:21 | nestedAB [a] | struct_init.c:31:23:31:23 | a |
|
||||
nodes
|
||||
| A.cpp:41:15:41:21 | new | semmle.label | new |
|
||||
| A.cpp:43:10:43:12 | & ... | semmle.label | & ... |
|
||||
| A.cpp:47:12:47:18 | new | semmle.label | new |
|
||||
| A.cpp:48:12:48:18 | call to make [c] | semmle.label | call to make [c] |
|
||||
| A.cpp:48:20:48:20 | c | semmle.label | c |
|
||||
| A.cpp:49:10:49:10 | b [c] | semmle.label | b [c] |
|
||||
| A.cpp:49:13:49:13 | c | semmle.label | c |
|
||||
| A.cpp:55:5:55:5 | b [post update] [c] | semmle.label | b [post update] [c] |
|
||||
| A.cpp:55:12:55:19 | new | semmle.label | new |
|
||||
| A.cpp:56:10:56:10 | b [c] | semmle.label | b [c] |
|
||||
| A.cpp:56:13:56:15 | call to get | semmle.label | call to get |
|
||||
| A.cpp:57:11:57:24 | call to B [c] | semmle.label | call to B [c] |
|
||||
| A.cpp:57:11:57:24 | new [c] | semmle.label | new [c] |
|
||||
| A.cpp:57:17:57:23 | new | semmle.label | new |
|
||||
| A.cpp:57:28:57:30 | call to get | semmle.label | call to get |
|
||||
| A.cpp:64:10:64:15 | call to setOnB [c] | semmle.label | call to setOnB [c] |
|
||||
| A.cpp:64:21:64:28 | new | semmle.label | new |
|
||||
| A.cpp:66:10:66:11 | b2 [c] | semmle.label | b2 [c] |
|
||||
| A.cpp:66:14:66:14 | c | semmle.label | c |
|
||||
| A.cpp:73:10:73:19 | call to setOnBWrap [c] | semmle.label | call to setOnBWrap [c] |
|
||||
| A.cpp:73:25:73:32 | new | semmle.label | new |
|
||||
| A.cpp:75:10:75:11 | b2 [c] | semmle.label | b2 [c] |
|
||||
| A.cpp:75:14:75:14 | c | semmle.label | c |
|
||||
| A.cpp:98:12:98:18 | new | semmle.label | new |
|
||||
| A.cpp:100:5:100:6 | c1 [post update] [a] | semmle.label | c1 [post update] [a] |
|
||||
| A.cpp:100:5:100:13 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:101:8:101:9 | c1 [a] | semmle.label | c1 [a] |
|
||||
| A.cpp:103:14:103:14 | c [a] | semmle.label | c [a] |
|
||||
| A.cpp:107:12:107:13 | c1 [a] | semmle.label | c1 [a] |
|
||||
| A.cpp:107:16:107:16 | a | semmle.label | a |
|
||||
| A.cpp:120:12:120:13 | c1 [a] | semmle.label | c1 [a] |
|
||||
| A.cpp:120:16:120:16 | a | semmle.label | a |
|
||||
| A.cpp:126:5:126:5 | b [post update] [c] | semmle.label | b [post update] [c] |
|
||||
| A.cpp:126:12:126:18 | new | semmle.label | new |
|
||||
| A.cpp:131:8:131:8 | ref arg b [c] | semmle.label | ref arg b [c] |
|
||||
| A.cpp:132:10:132:10 | b [c] | semmle.label | b [c] |
|
||||
| A.cpp:132:13:132:13 | c | semmle.label | c |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c] | semmle.label | b [post update] [c] |
|
||||
| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:142:14:142:20 | new | semmle.label | new |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b, c] | semmle.label | this [post update] [b, c] |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b] | semmle.label | this [post update] [b] |
|
||||
| A.cpp:143:7:143:31 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:143:7:143:31 | ... = ... [c] | semmle.label | ... = ... [c] |
|
||||
| A.cpp:143:25:143:31 | new | semmle.label | new |
|
||||
| A.cpp:150:12:150:18 | new | semmle.label | new |
|
||||
| A.cpp:151:12:151:24 | call to D [b, c] | semmle.label | call to D [b, c] |
|
||||
| A.cpp:151:12:151:24 | call to D [b] | semmle.label | call to D [b] |
|
||||
| A.cpp:151:18:151:18 | b | semmle.label | b |
|
||||
| A.cpp:151:18:151:18 | ref arg b [c] | semmle.label | ref arg b [c] |
|
||||
| A.cpp:152:10:152:10 | d [b] | semmle.label | d [b] |
|
||||
| A.cpp:152:13:152:13 | b | semmle.label | b |
|
||||
| A.cpp:153:10:153:10 | d [b, c] | semmle.label | d [b, c] |
|
||||
| A.cpp:153:13:153:13 | b [c] | semmle.label | b [c] |
|
||||
| A.cpp:153:16:153:16 | c | semmle.label | c |
|
||||
| A.cpp:154:10:154:10 | b [c] | semmle.label | b [c] |
|
||||
| A.cpp:154:13:154:13 | c | semmle.label | c |
|
||||
| A.cpp:159:12:159:18 | new | semmle.label | new |
|
||||
| A.cpp:160:18:160:60 | call to MyList [head] | semmle.label | call to MyList [head] |
|
||||
| A.cpp:160:29:160:29 | b | semmle.label | b |
|
||||
| A.cpp:161:18:161:40 | call to MyList [next, head] | semmle.label | call to MyList [next, head] |
|
||||
| A.cpp:161:38:161:39 | l1 [head] | semmle.label | l1 [head] |
|
||||
| A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] | semmle.label | call to MyList [next, next, ... (3)] |
|
||||
| A.cpp:162:38:162:39 | l2 [next, head] | semmle.label | l2 [next, head] |
|
||||
| A.cpp:165:10:165:11 | l3 [next, next, ... (3)] | semmle.label | l3 [next, next, ... (3)] |
|
||||
| A.cpp:165:14:165:17 | next [next, head] | semmle.label | next [next, head] |
|
||||
| A.cpp:165:20:165:23 | next [head] | semmle.label | next [head] |
|
||||
| A.cpp:165:26:165:29 | head | semmle.label | head |
|
||||
| A.cpp:167:44:167:44 | l [next, head] | semmle.label | l [next, head] |
|
||||
| A.cpp:167:44:167:44 | l [next, next, ... (3)] | semmle.label | l [next, next, ... (3)] |
|
||||
| A.cpp:167:47:167:50 | next [head] | semmle.label | next [head] |
|
||||
| A.cpp:167:47:167:50 | next [next, head] | semmle.label | next [next, head] |
|
||||
| A.cpp:169:12:169:12 | l [head] | semmle.label | l [head] |
|
||||
| A.cpp:169:15:169:18 | head | semmle.label | head |
|
||||
| B.cpp:6:15:6:24 | new | semmle.label | new |
|
||||
| B.cpp:7:16:7:35 | call to Box1 [elem1] | semmle.label | call to Box1 [elem1] |
|
||||
| B.cpp:7:25:7:25 | e | semmle.label | e |
|
||||
| B.cpp:8:16:8:27 | call to Box2 [box1, elem1] | semmle.label | call to Box2 [box1, elem1] |
|
||||
| B.cpp:8:25:8:26 | b1 [elem1] | semmle.label | b1 [elem1] |
|
||||
| B.cpp:9:10:9:11 | b2 [box1, elem1] | semmle.label | b2 [box1, elem1] |
|
||||
| B.cpp:9:14:9:17 | box1 [elem1] | semmle.label | box1 [elem1] |
|
||||
| B.cpp:9:20:9:24 | elem1 | semmle.label | elem1 |
|
||||
| B.cpp:15:15:15:27 | new | semmle.label | new |
|
||||
| B.cpp:16:16:16:38 | call to Box1 [elem2] | semmle.label | call to Box1 [elem2] |
|
||||
| B.cpp:16:37:16:37 | e | semmle.label | e |
|
||||
| B.cpp:17:16:17:27 | call to Box2 [box1, elem2] | semmle.label | call to Box2 [box1, elem2] |
|
||||
| B.cpp:17:25:17:26 | b1 [elem2] | semmle.label | b1 [elem2] |
|
||||
| B.cpp:19:10:19:11 | b2 [box1, elem2] | semmle.label | b2 [box1, elem2] |
|
||||
| B.cpp:19:14:19:17 | box1 [elem2] | semmle.label | box1 [elem2] |
|
||||
| B.cpp:19:20:19:24 | elem2 | semmle.label | elem2 |
|
||||
| C.cpp:18:12:18:18 | call to C [s1] | semmle.label | call to C [s1] |
|
||||
| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] |
|
||||
| C.cpp:19:5:19:5 | c [s1] | semmle.label | c [s1] |
|
||||
| C.cpp:19:5:19:5 | c [s3] | semmle.label | c [s3] |
|
||||
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | semmle.label | constructor init of field s1 [post-this] [s1] |
|
||||
| C.cpp:22:12:22:21 | new | semmle.label | new |
|
||||
| C.cpp:24:5:24:8 | this [post update] [s3] | semmle.label | this [post update] [s3] |
|
||||
| C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... |
|
||||
| C.cpp:24:16:24:25 | new | semmle.label | new |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s1] | semmle.label | `this` parameter in func [s1] |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s3] | semmle.label | `this` parameter in func [s3] |
|
||||
| C.cpp:29:10:29:11 | s1 | semmle.label | s1 |
|
||||
| C.cpp:29:10:29:11 | this [s1] | semmle.label | this [s1] |
|
||||
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
|
||||
| C.cpp:31:10:31:11 | this [s3] | semmle.label | this [s3] |
|
||||
| D.cpp:21:30:21:31 | b2 [box, elem] | semmle.label | b2 [box, elem] |
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | semmle.label | b2 [box, elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | semmle.label | call to getBox1 [elem] |
|
||||
| D.cpp:22:25:22:31 | call to getElem | semmle.label | call to getElem |
|
||||
| D.cpp:28:15:28:24 | new | semmle.label | new |
|
||||
| D.cpp:30:5:30:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] |
|
||||
| D.cpp:30:5:30:20 | ... = ... | semmle.label | ... = ... |
|
||||
| D.cpp:30:8:30:10 | box [post update] [elem] | semmle.label | box [post update] [elem] |
|
||||
| D.cpp:31:14:31:14 | b [box, elem] | semmle.label | b [box, elem] |
|
||||
| D.cpp:35:15:35:24 | new | semmle.label | new |
|
||||
| D.cpp:37:5:37:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] |
|
||||
| D.cpp:37:8:37:10 | box [post update] [elem] | semmle.label | box [post update] [elem] |
|
||||
| D.cpp:37:21:37:21 | e | semmle.label | e |
|
||||
| D.cpp:38:14:38:14 | b [box, elem] | semmle.label | b [box, elem] |
|
||||
| D.cpp:42:15:42:24 | new | semmle.label | new |
|
||||
| D.cpp:44:5:44:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] |
|
||||
| D.cpp:44:5:44:26 | ... = ... | semmle.label | ... = ... |
|
||||
| D.cpp:44:8:44:14 | call to getBox1 [post update] [elem] | semmle.label | call to getBox1 [post update] [elem] |
|
||||
| D.cpp:45:14:45:14 | b [box, elem] | semmle.label | b [box, elem] |
|
||||
| D.cpp:49:15:49:24 | new | semmle.label | new |
|
||||
| D.cpp:51:5:51:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] |
|
||||
| D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | semmle.label | call to getBox1 [post update] [elem] |
|
||||
| D.cpp:51:27:51:27 | e | semmle.label | e |
|
||||
| D.cpp:52:14:52:14 | b [box, elem] | semmle.label | b [box, elem] |
|
||||
| D.cpp:56:15:56:24 | new | semmle.label | new |
|
||||
| D.cpp:58:5:58:12 | boxfield [post update] [box, elem] | semmle.label | boxfield [post update] [box, elem] |
|
||||
| D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] | semmle.label | this [post update] [boxfield, box, ... (3)] |
|
||||
| D.cpp:58:5:58:27 | ... = ... | semmle.label | ... = ... |
|
||||
| D.cpp:58:15:58:17 | box [post update] [elem] | semmle.label | box [post update] [elem] |
|
||||
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | semmle.label | `this` parameter in f5b [boxfield, box, ... (3)] |
|
||||
| D.cpp:64:10:64:17 | boxfield [box, elem] | semmle.label | boxfield [box, elem] |
|
||||
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:64:20:64:22 | box [elem] | semmle.label | box [elem] |
|
||||
| D.cpp:64:25:64:28 | elem | semmle.label | elem |
|
||||
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
|
||||
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
|
||||
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
|
||||
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
|
||||
| aliasing.cpp:13:3:13:21 | ... = ... | semmle.label | ... = ... |
|
||||
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
|
||||
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | semmle.label | ref arg & ... [m1] |
|
||||
| aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | semmle.label | ref arg s2 [m1] |
|
||||
| aliasing.cpp:29:8:29:9 | s1 [m1] | semmle.label | s1 [m1] |
|
||||
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:30:8:30:9 | s2 [m1] | semmle.label | s2 [m1] |
|
||||
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | semmle.label | s2 [post update] [m1] |
|
||||
| aliasing.cpp:60:3:60:22 | ... = ... | semmle.label | ... = ... |
|
||||
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
|
||||
| aliasing.cpp:62:8:62:12 | copy2 [m1] | semmle.label | copy2 [m1] |
|
||||
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | semmle.label | w [post update] [s, m1] |
|
||||
| aliasing.cpp:92:3:92:23 | ... = ... | semmle.label | ... = ... |
|
||||
| aliasing.cpp:92:5:92:5 | s [post update] [m1] | semmle.label | s [post update] [m1] |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
|
||||
| aliasing.cpp:93:8:93:8 | w [s, m1] | semmle.label | w [s, m1] |
|
||||
| aliasing.cpp:93:10:93:10 | s [m1] | semmle.label | s [m1] |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
|
||||
| by_reference.cpp:50:3:50:3 | s [post update] [a] | semmle.label | s [post update] [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | semmle.label | s [a] |
|
||||
| by_reference.cpp:51:10:51:20 | call to getDirectly | semmle.label | call to getDirectly |
|
||||
| by_reference.cpp:56:3:56:3 | s [post update] [a] | semmle.label | s [post update] [a] |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:57:8:57:8 | s [a] | semmle.label | s [a] |
|
||||
| by_reference.cpp:57:10:57:22 | call to getIndirectly | semmle.label | call to getIndirectly |
|
||||
| by_reference.cpp:62:3:62:3 | s [post update] [a] | semmle.label | s [post update] [a] |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:63:8:63:8 | s [a] | semmle.label | s [a] |
|
||||
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | semmle.label | call to getThroughNonMember |
|
||||
| complex.cpp:34:15:34:15 | b [f, a_] | semmle.label | b [f, a_] |
|
||||
| complex.cpp:34:15:34:15 | b [f, b_] | semmle.label | b [f, b_] |
|
||||
| complex.cpp:44:8:44:8 | b [f, a_] | semmle.label | b [f, a_] |
|
||||
| complex.cpp:44:10:44:10 | f [a_] | semmle.label | f [a_] |
|
||||
| complex.cpp:44:12:44:12 | call to a | semmle.label | call to a |
|
||||
| complex.cpp:45:8:45:8 | b [f, b_] | semmle.label | b [f, b_] |
|
||||
| complex.cpp:45:10:45:10 | f [b_] | semmle.label | f [b_] |
|
||||
| complex.cpp:45:12:45:12 | call to b | semmle.label | call to b |
|
||||
| complex.cpp:55:3:55:4 | b1 [post update] [f, a_] | semmle.label | b1 [post update] [f, a_] |
|
||||
| complex.cpp:55:6:55:6 | f [post update] [a_] | semmle.label | f [post update] [a_] |
|
||||
| complex.cpp:55:13:55:22 | call to user_input | semmle.label | call to user_input |
|
||||
| complex.cpp:56:3:56:4 | b2 [post update] [f, b_] | semmle.label | b2 [post update] [f, b_] |
|
||||
| complex.cpp:56:6:56:6 | f [post update] [b_] | semmle.label | f [post update] [b_] |
|
||||
| complex.cpp:56:13:56:22 | call to user_input | semmle.label | call to user_input |
|
||||
| complex.cpp:57:3:57:4 | b3 [post update] [f, a_] | semmle.label | b3 [post update] [f, a_] |
|
||||
| complex.cpp:57:6:57:6 | f [post update] [a_] | semmle.label | f [post update] [a_] |
|
||||
| complex.cpp:57:13:57:22 | call to user_input | semmle.label | call to user_input |
|
||||
| complex.cpp:58:3:58:4 | b3 [post update] [f, b_] | semmle.label | b3 [post update] [f, b_] |
|
||||
| complex.cpp:58:6:58:6 | f [post update] [b_] | semmle.label | f [post update] [b_] |
|
||||
| complex.cpp:58:13:58:22 | call to user_input | semmle.label | call to user_input |
|
||||
| complex.cpp:61:7:61:8 | b1 [f, a_] | semmle.label | b1 [f, a_] |
|
||||
| complex.cpp:64:7:64:8 | b2 [f, b_] | semmle.label | b2 [f, b_] |
|
||||
| complex.cpp:67:7:67:8 | b3 [f, a_] | semmle.label | b3 [f, a_] |
|
||||
| complex.cpp:67:7:67:8 | b3 [f, b_] | semmle.label | b3 [f, b_] |
|
||||
| constructors.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
|
||||
| constructors.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
|
||||
| constructors.cpp:28:12:28:12 | call to a | semmle.label | call to a |
|
||||
| constructors.cpp:29:10:29:10 | f [b_] | semmle.label | f [b_] |
|
||||
| constructors.cpp:29:12:29:12 | call to b | semmle.label | call to b |
|
||||
| constructors.cpp:34:11:34:20 | call to user_input | semmle.label | call to user_input |
|
||||
| constructors.cpp:34:11:34:26 | call to Foo [a_] | semmle.label | call to Foo [a_] |
|
||||
| constructors.cpp:35:11:35:26 | call to Foo [b_] | semmle.label | call to Foo [b_] |
|
||||
| constructors.cpp:35:14:35:23 | call to user_input | semmle.label | call to user_input |
|
||||
| constructors.cpp:36:11:36:20 | call to user_input | semmle.label | call to user_input |
|
||||
| constructors.cpp:36:11:36:37 | call to Foo [a_] | semmle.label | call to Foo [a_] |
|
||||
| constructors.cpp:36:11:36:37 | call to Foo [b_] | semmle.label | call to Foo [b_] |
|
||||
| constructors.cpp:36:25:36:34 | call to user_input | semmle.label | call to user_input |
|
||||
| constructors.cpp:40:9:40:9 | f [a_] | semmle.label | f [a_] |
|
||||
| constructors.cpp:43:9:43:9 | g [b_] | semmle.label | g [b_] |
|
||||
| constructors.cpp:46:9:46:9 | h [a_] | semmle.label | h [a_] |
|
||||
| constructors.cpp:46:9:46:9 | h [b_] | semmle.label | h [b_] |
|
||||
| simple.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
|
||||
| simple.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
|
||||
| simple.cpp:28:12:28:12 | call to a | semmle.label | call to a |
|
||||
| simple.cpp:29:10:29:10 | f [b_] | semmle.label | f [b_] |
|
||||
| simple.cpp:29:12:29:12 | call to b | semmle.label | call to b |
|
||||
| simple.cpp:39:5:39:5 | f [post update] [a_] | semmle.label | f [post update] [a_] |
|
||||
| simple.cpp:39:12:39:21 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:40:5:40:5 | g [post update] [b_] | semmle.label | g [post update] [b_] |
|
||||
| simple.cpp:40:12:40:21 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:41:5:41:5 | h [post update] [a_] | semmle.label | h [post update] [a_] |
|
||||
| simple.cpp:41:12:41:21 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:42:5:42:5 | h [post update] [b_] | semmle.label | h [post update] [b_] |
|
||||
| simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:45:9:45:9 | f [a_] | semmle.label | f [a_] |
|
||||
| simple.cpp:48:9:48:9 | g [b_] | semmle.label | g [b_] |
|
||||
| simple.cpp:51:9:51:9 | h [a_] | semmle.label | h [a_] |
|
||||
| simple.cpp:51:9:51:9 | h [b_] | semmle.label | h [b_] |
|
||||
| struct_init.c:20:17:20:36 | {...} [a] | semmle.label | {...} [a] |
|
||||
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
|
||||
| struct_init.c:22:8:22:9 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:22:11:22:11 | a | semmle.label | a |
|
||||
| struct_init.c:26:23:29:3 | {...} [nestedAB, a] | semmle.label | {...} [nestedAB, a] |
|
||||
| struct_init.c:27:5:27:23 | {...} [a] | semmle.label | {...} [a] |
|
||||
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
|
||||
| struct_init.c:31:8:31:12 | outer [nestedAB, a] | semmle.label | outer [nestedAB, a] |
|
||||
| struct_init.c:31:14:31:21 | nestedAB [a] | semmle.label | nestedAB [a] |
|
||||
| struct_init.c:31:23:31:23 | a | semmle.label | a |
|
||||
#select
|
||||
| A.cpp:43:10:43:12 | & ... | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... | & ... flows from $@ | A.cpp:41:15:41:21 | new | new |
|
||||
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
|
||||
|
||||
@@ -20,6 +20,7 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C |
|
||||
| ms_try_mix.cpp:28:12:28:15 | Chi: call to C |
|
||||
| ms_try_mix.cpp:48:10:48:13 | Chi: call to C |
|
||||
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31268 | 31268 | f2 |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31274 | 31274 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31277 | 31277 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31280 | 31280 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31283 | 31283 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31286 | 31286 | return ... |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31289 | 31289 | { ... } |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31292 | 31292 | call to C |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31295 | 31295 | initializer for c |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31298 | 31298 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31304 | 31304 | 2 |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31309 | 31309 | initializer for j |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31311 | 31311 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31319 | 31319 | 2 |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31321 | 31321 | initializer for two |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31325 | 31325 | two |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 31333 | 31333 | initializer for i |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31274 | 31321 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31277 | 31280 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31280 | 31283 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31283 | 31286 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31286 | 31268 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31289 | 31274 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31319 | 31277 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 31321 | 31319 | |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31268 | 31268 | f2 |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31274 | 31274 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31277 | 31277 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31280 | 31280 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31283 | 31283 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31286 | 31286 | return ... |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31289 | 31289 | { ... } |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31292 | 31292 | call to C |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31295 | 31295 | initializer for c |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31298 | 31298 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31304 | 31304 | 2 |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31309 | 31309 | initializer for j |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31311 | 31311 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31319 | 31319 | 2 |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31321 | 31321 | initializer for two |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31325 | 31325 | two |
|
||||
| staticlocals__staticlocals_f2_ql | false | 31333 | 31333 | initializer for i |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31274 | 31321 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31277 | 31280 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31280 | 31283 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31283 | 31286 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31283 | 31295 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31286 | 31268 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31289 | 31274 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31292 | 31286 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31295 | 31292 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31319 | 31277 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 31321 | 31319 | |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22465 | 22465 | f2 |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22470 | 22470 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22472 | 22472 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22474 | 22474 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22476 | 22476 | declaration |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22478 | 22478 | return ... |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22480 | 22480 | { ... } |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22482 | 22482 | call to C |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22484 | 22484 | initializer for c |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22486 | 22486 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22490 | 22490 | 2 |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22493 | 22493 | initializer for j |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22494 | 22494 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22499 | 22499 | 2 |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22500 | 22500 | initializer for two |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22503 | 22503 | two |
|
||||
| staticlocals__staticlocals_f2_extractor | false | 22508 | 22508 | initializer for i |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22470 | 22500 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22472 | 22474 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22474 | 22476 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22476 | 22478 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22478 | 22465 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22480 | 22470 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22499 | 22472 | |
|
||||
| staticlocals__staticlocals_f2_extractor | true | 22500 | 22499 | |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22465 | 22465 | f2 |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22470 | 22470 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22472 | 22472 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22474 | 22474 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22476 | 22476 | declaration |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22478 | 22478 | return ... |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22480 | 22480 | { ... } |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22482 | 22482 | call to C |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22484 | 22484 | initializer for c |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22486 | 22486 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22490 | 22490 | 2 |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22493 | 22493 | initializer for j |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22494 | 22494 | call to addOne |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22499 | 22499 | 2 |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22500 | 22500 | initializer for two |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22503 | 22503 | two |
|
||||
| staticlocals__staticlocals_f2_ql | false | 22508 | 22508 | initializer for i |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22470 | 22500 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22472 | 22474 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22474 | 22476 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22476 | 22478 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22476 | 22484 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22478 | 22465 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22480 | 22470 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22482 | 22478 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22484 | 22482 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22499 | 22472 | |
|
||||
| staticlocals__staticlocals_f2_ql | true | 22500 | 22499 | |
|
||||
|
||||
@@ -28,3 +28,9 @@ int usePM(int PM::* pm) {
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
void pmIsConst() {
|
||||
static const struct {
|
||||
int PM::* pm1;
|
||||
} pms = { &PM::x1 };
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ missingOperand
|
||||
| misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| pointer_to_member.cpp:35:13:35:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| range_analysis.c:368:10:368:21 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
|
||||
| range_analysis.c:369:10:369:36 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
|
||||
| range_analysis.c:370:10:370:38 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
|
||||
@@ -65,6 +66,7 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
|
||||
| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... |
|
||||
| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } |
|
||||
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
|
||||
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:89:27:89:36 | Convert: (void *)... |
|
||||
@@ -671,6 +673,7 @@ useNotDominatedByDefinition
|
||||
| ms_try_mix.cpp:38:16:38:19 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) |
|
||||
| ms_try_mix.cpp:41:12:41:15 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) |
|
||||
| ms_try_mix.cpp:51:5:51:11 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() |
|
||||
| pointer_to_member.cpp:35:13:35:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| stmt_expr.cpp:30:20:30:21 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
|
||||
| stmt_expr.cpp:31:16:31:18 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
|
||||
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) |
|
||||
|
||||
@@ -29,6 +29,7 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C |
|
||||
| ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C |
|
||||
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
|
||||
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
|
||||
@@ -1,35 +1,44 @@
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:25:12:25:16 | pi | 0 | T |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:25:12:25:16 | pi | 0 | float |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:25:12:25:16 | pi | 0 | int |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:37:16:37:24 | pi | 0 | float |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:38:16:38:22 | pi | 0 | int |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | multi_arg | 0 | S |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | multi_arg | 0 | float |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | multi_arg | 0 | short |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | multi_arg | 1 | T |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | multi_arg | 1 | char |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | multi_arg | 1 | long |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:40:23:40:60 | multi_arg | 0 | unsigned int |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:40:23:40:60 | multi_arg | 1 | unsigned char |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:41:23:41:42 | multi_arg | 0 | int |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:41:23:41:42 | multi_arg | 1 | char |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:26:3:26:16 | mutable_val | 0 | T |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:26:3:26:16 | mutable_val | 0 | float |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:26:3:26:16 | mutable_val | 0 | int |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:43:3:43:18 | mutable_val | 0 | int |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:44:3:44:19 | mutable_val | 0 | long |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:27:3:27:13 | bar | 0 | T |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:27:3:27:13 | bar | 0 | float |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:27:3:27:13 | bar | 0 | int |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:46:3:46:17 | bar | 0 | short |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:47:3:47:18 | bar | 0 | double |
|
||||
| variables.cpp:21:5:21:15 | no_template | variables.cpp:28:3:28:13 | no_template | -1 | <none> |
|
||||
| variables.cpp:21:5:21:15 | no_template | variables.cpp:28:3:28:13 | no_template | -1 | <none> |
|
||||
| variables.cpp:21:5:21:15 | no_template | variables.cpp:28:3:28:13 | no_template | -1 | <none> |
|
||||
| variables.cpp:21:5:21:15 | no_template | variables.cpp:49:3:49:13 | no_template | -1 | <none> |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:26:20:26:22 | val | -1 | <none> |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:26:20:26:22 | val | -1 | <none> |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:26:20:26:22 | val | -1 | <none> |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:27:17:27:19 | val | -1 | <none> |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:27:17:27:19 | val | -1 | <none> |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:27:17:27:19 | val | -1 | <none> |
|
||||
| file://:0:0:0:0 | fp_offset | | | |
|
||||
| file://:0:0:0:0 | gp_offset | | | |
|
||||
| file://:0:0:0:0 | overflow_arg_area | | | |
|
||||
| file://:0:0:0:0 | p#0 | | | |
|
||||
| file://:0:0:0:0 | p#0 | | | |
|
||||
| file://:0:0:0:0 | p#0 | | | |
|
||||
| file://:0:0:0:0 | p#0 | | | |
|
||||
| file://:0:0:0:0 | reg_save_area | | | |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:25:12:25:16 | T | |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:25:12:25:16, variables.cpp:37:16:37:24 | float | |
|
||||
| variables.cpp:2:13:2:13 | pi | variables.cpp:25:12:25:16, variables.cpp:38:16:38:22 | int | |
|
||||
| variables.cpp:2:16:2:16 | pi | | T | TemplateVariable |
|
||||
| variables.cpp:5:23:5:37 | pi | | const char * | |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | S, T | |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | float, char | |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:33:19:33:33 | short, long | |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:40:23:40:60 | unsigned int, unsigned char | |
|
||||
| variables.cpp:8:13:8:13 | multi_arg | variables.cpp:41:23:41:42 | int, char | |
|
||||
| variables.cpp:8:23:8:23 | multi_arg | | S, T | TemplateVariable |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:26:3:26:16 | T | |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:26:3:26:16 | float | |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:26:3:26:16, variables.cpp:43:3:43:18 | int | |
|
||||
| variables.cpp:11:3:11:3 | mutable_val | variables.cpp:44:3:44:19 | long | |
|
||||
| variables.cpp:11:15:11:15 | mutable_val | | T | TemplateVariable |
|
||||
| variables.cpp:19:3:19:10 | bar | | T | TemplateVariable |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:27:3:27:13 | T | |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:27:3:27:13 | float | |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:27:3:27:13 | int | |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:46:3:46:17 | short | |
|
||||
| variables.cpp:19:8:19:8 | bar | variables.cpp:47:3:47:18 | double | |
|
||||
| variables.cpp:21:5:21:15 | no_template | variables.cpp:28:3:28:13, variables.cpp:28:3:28:13, variables.cpp:28:3:28:13, variables.cpp:49:3:49:13 | | |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:26:20:26:22, variables.cpp:27:17:27:19 | | |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:26:20:26:22, variables.cpp:27:17:27:19 | | |
|
||||
| variables.cpp:24:27:24:29 | val | variables.cpp:26:20:26:22, variables.cpp:27:17:27:19 | | |
|
||||
| variables.cpp:25:5:25:8 | pi_t | | | |
|
||||
| variables.cpp:25:5:25:8 | pi_t | | | |
|
||||
| variables.cpp:25:5:25:8 | pi_t | | | |
|
||||
| variables.cpp:33:5:33:15 | multi_arg_s | | | |
|
||||
| variables.cpp:33:5:33:15 | multi_arg_s | | | |
|
||||
| variables.cpp:33:5:33:15 | multi_arg_s | | | |
|
||||
| variables.cpp:37:9:37:12 | pi_f | | | |
|
||||
| variables.cpp:38:9:38:12 | pi_i | | | |
|
||||
| variables.cpp:40:9:40:19 | multi_arg_a | | | |
|
||||
| variables.cpp:41:9:41:19 | multi_arg_b | | | |
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import cpp
|
||||
|
||||
from Variable v, VariableAccess a, int i, string s
|
||||
where
|
||||
v = a.getTarget() and
|
||||
if exists(v.getATemplateArgument())
|
||||
then s = v.getTemplateArgument(i).toString()
|
||||
else (
|
||||
s = "<none>" and i = -1
|
||||
)
|
||||
select v, a, i, s
|
||||
string describe(Variable v) {
|
||||
v instanceof TemplateVariable and
|
||||
result = "TemplateVariable"
|
||||
}
|
||||
|
||||
from Variable v
|
||||
select v, concat(VariableAccess a | a.getTarget() = v | a.getLocation().toString(), ", "),
|
||||
concat(int i | | v.getTemplateArgument(i).toString(), ", " order by i), concat(describe(v), ", ")
|
||||
|
||||
@@ -14,6 +14,26 @@ edges
|
||||
| test.cpp:88:21:88:22 | d2 | test.cpp:34:31:34:31 | b |
|
||||
| test.cpp:95:21:95:21 | d | test.cpp:50:31:50:31 | b |
|
||||
| test.cpp:96:21:96:23 | dss | test.cpp:50:31:50:31 | b |
|
||||
nodes
|
||||
| test.cpp:26:29:26:29 | b | semmle.label | b |
|
||||
| test.cpp:27:2:27:2 | b | semmle.label | b |
|
||||
| test.cpp:30:34:30:34 | b | semmle.label | b |
|
||||
| test.cpp:31:2:31:2 | b | semmle.label | b |
|
||||
| test.cpp:34:31:34:31 | b | semmle.label | b |
|
||||
| test.cpp:35:2:35:2 | b | semmle.label | b |
|
||||
| test.cpp:50:31:50:31 | b | semmle.label | b |
|
||||
| test.cpp:51:11:51:11 | b | semmle.label | b |
|
||||
| test.cpp:57:19:57:19 | d | semmle.label | d |
|
||||
| test.cpp:58:25:58:25 | d | semmle.label | d |
|
||||
| test.cpp:59:21:59:21 | d | semmle.label | d |
|
||||
| test.cpp:74:19:74:21 | dss | semmle.label | dss |
|
||||
| test.cpp:75:25:75:27 | dss | semmle.label | dss |
|
||||
| test.cpp:76:21:76:23 | dss | semmle.label | dss |
|
||||
| test.cpp:86:19:86:20 | d2 | semmle.label | d2 |
|
||||
| test.cpp:87:25:87:26 | d2 | semmle.label | d2 |
|
||||
| test.cpp:88:21:88:22 | d2 | semmle.label | d2 |
|
||||
| test.cpp:95:21:95:21 | d | semmle.label | d |
|
||||
| test.cpp:96:21:96:23 | dss | semmle.label | dss |
|
||||
#select
|
||||
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:57:19:57:19 | d | here |
|
||||
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:74:19:74:21 | dss | here |
|
||||
|
||||
@@ -92,6 +92,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case SymbolKind.Event:
|
||||
kind = ExprKind.EVENT_ACCESS;
|
||||
break;
|
||||
case SymbolKind.Namespace:
|
||||
kind = ExprKind.NAMESPACE_ACCESS;
|
||||
break;
|
||||
default:
|
||||
info.Context.ModelError(info.Node, "Unhandled symbol for member access");
|
||||
kind = ExprKind.UNKNOWN;
|
||||
|
||||
@@ -567,6 +567,7 @@ module AssignableDefinitions {
|
||||
* entry point of `p`'s callable to basic block `bb` without passing through
|
||||
* any assignments to `p`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate parameterReachesWithoutDef(Parameter p, ControlFlow::BasicBlock bb) {
|
||||
forall(AssignableDefinition def | basicBlockRefParamDef(bb, p, def) |
|
||||
isUncertainRefCall(def.getTargetAccess())
|
||||
|
||||
@@ -65,6 +65,7 @@ predicate implements(Virtualizable m1, Virtualizable m2, ValueOrRefType t) {
|
||||
* `I.M()` is compatible with `A.M()` for types `A` and `B`, but not
|
||||
* for type `C`, because `C.M()` conflicts.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Virtualizable getAnImplementedInterfaceMemberForSubType(Virtualizable m, ValueOrRefType t) {
|
||||
result = getACompatibleInterfaceMember(m) and
|
||||
t = m.getDeclaringType()
|
||||
@@ -86,6 +87,7 @@ private predicate hasMemberCompatibleWithInterfaceMember(ValueOrRefType t, Virtu
|
||||
* signature, and where `m` can potentially be accessed when
|
||||
* the interface member is accessed.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Virtualizable getACompatibleInterfaceMember(Virtualizable m) {
|
||||
result = getACompatibleInterfaceMemberAux(m) and
|
||||
(
|
||||
@@ -97,12 +99,14 @@ private Virtualizable getACompatibleInterfaceMember(Virtualizable m) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Virtualizable getACompatibleExplicitInterfaceMember(Virtualizable m, ValueOrRefType declType) {
|
||||
result = getACompatibleInterfaceMemberAux(m) and
|
||||
declType = m.getDeclaringType() and
|
||||
m.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Virtualizable getACompatibleInterfaceMemberAux(Virtualizable m) {
|
||||
result = getACompatibleInterfaceAccessor(m) or
|
||||
result = getACompatibleInterfaceIndexer(m) or
|
||||
|
||||
@@ -32,19 +32,19 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
|
||||
* several `ControlFlow::Node`s, for example to represent the continuation
|
||||
* flow in a `try/catch/finally` construction.
|
||||
*/
|
||||
Node getAControlFlowNode() { result.getElement() = this }
|
||||
Nodes::ElementNode getAControlFlowNode() { result.getElement() = this }
|
||||
|
||||
/**
|
||||
* Gets a first control flow node executed within this element.
|
||||
*/
|
||||
Node getAControlFlowEntryNode() {
|
||||
Nodes::ElementNode getAControlFlowEntryNode() {
|
||||
result = Internal::getAControlFlowEntryNode(this).getAControlFlowNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a potential last control flow node executed within this element.
|
||||
*/
|
||||
Node getAControlFlowExitNode() {
|
||||
Nodes::ElementNode getAControlFlowExitNode() {
|
||||
result = Internal::getAControlFlowExitNode(this).getAControlFlowNode()
|
||||
}
|
||||
|
||||
|
||||
@@ -317,6 +317,8 @@ module ControlFlow {
|
||||
class ExceptionHandlerSplit = ExceptionHandlerSplitting::ExceptionHandlerSplitImpl;
|
||||
|
||||
class BooleanSplit = BooleanSplitting::BooleanSplitImpl;
|
||||
|
||||
class LoopUnrollingSplit = LoopUnrollingSplitting::LoopUnrollingSplitImpl;
|
||||
}
|
||||
|
||||
class BasicBlock = BBs::BasicBlock;
|
||||
|
||||
@@ -12,6 +12,9 @@ private import semmle.code.csharp.commons.StructuralComparison::Internal
|
||||
private import semmle.code.csharp.controlflow.BasicBlocks
|
||||
private import semmle.code.csharp.controlflow.internal.Completion
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.frameworks.system.Linq
|
||||
private import semmle.code.csharp.frameworks.system.Collections
|
||||
private import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
|
||||
/** An expression whose value may control the execution of another element. */
|
||||
class Guard extends Expr {
|
||||
@@ -53,6 +56,28 @@ abstract class AbstractValue extends TAbstractValue {
|
||||
*/
|
||||
abstract predicate isSingleton();
|
||||
|
||||
/**
|
||||
* Holds if this value describes a referential property. For example, emptiness
|
||||
* of a collection is a referential property.
|
||||
*
|
||||
* Such values only propagate through adjacent reads, for example, in
|
||||
*
|
||||
* ```
|
||||
* int M()
|
||||
* {
|
||||
* var x = new string[]{ "a", "b", "c" }.ToList();
|
||||
* x.Clear();
|
||||
* return x.Count;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* the non-emptiness of `new string[]{ "a", "b", "c" }.ToList()` only propagates
|
||||
* to the read of `x` in `x.Clear()` and not in `x.Count`.
|
||||
*
|
||||
* Aliasing is not taken into account in the analyses.
|
||||
*/
|
||||
predicate isReferentialProperty() { none() }
|
||||
|
||||
/** Gets a textual representation of this abstract value. */
|
||||
abstract string toString();
|
||||
}
|
||||
@@ -112,6 +137,9 @@ module AbstractValues {
|
||||
/** Holds if this value represents `null`. */
|
||||
predicate isNull() { this = TNullValue(true) }
|
||||
|
||||
/** Holds if this value represents non-`null`. */
|
||||
predicate isNonNull() { this = TNullValue(false) }
|
||||
|
||||
override predicate branch(ControlFlowElement cfe, ConditionalSuccessor s, Expr e) {
|
||||
this = TNullValue(s.(NullnessSuccessor).getValue()) and
|
||||
exists(NullnessCompletion c | s.matchesCompletion(c) |
|
||||
@@ -121,7 +149,7 @@ module AbstractValues {
|
||||
}
|
||||
|
||||
override NullValue getDualValue() {
|
||||
if this.isNull() then not result.isNull() else result.isNull()
|
||||
if this.isNull() then result.isNonNull() else result.isNull()
|
||||
}
|
||||
|
||||
override DereferenceableExpr getAnExpr() {
|
||||
@@ -174,6 +202,9 @@ module AbstractValues {
|
||||
/** Holds if this value represents an empty collection. */
|
||||
predicate isEmpty() { this = TEmptyCollectionValue(true) }
|
||||
|
||||
/** Holds if this value represents a non-empty collection. */
|
||||
predicate isNonEmpty() { this = TEmptyCollectionValue(false) }
|
||||
|
||||
override predicate branch(ControlFlowElement cfe, ConditionalSuccessor s, Expr e) {
|
||||
this = TEmptyCollectionValue(s.(EmptinessSuccessor).getValue()) and
|
||||
exists(EmptinessCompletion c, ForeachStmt fs | s.matchesCompletion(c) |
|
||||
@@ -184,13 +215,21 @@ module AbstractValues {
|
||||
}
|
||||
|
||||
override EmptyCollectionValue getDualValue() {
|
||||
if this.isEmpty() then not result.isEmpty() else result.isEmpty()
|
||||
if this.isEmpty() then result.isNonEmpty() else result.isEmpty()
|
||||
}
|
||||
|
||||
override Expr getAnExpr() { none() }
|
||||
override Expr getAnExpr() {
|
||||
this.isEmpty() and
|
||||
emptyValue(result)
|
||||
or
|
||||
this.isNonEmpty() and
|
||||
nonEmptyValue(result)
|
||||
}
|
||||
|
||||
override predicate isSingleton() { none() }
|
||||
|
||||
override predicate isReferentialProperty() { any() }
|
||||
|
||||
override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" }
|
||||
}
|
||||
}
|
||||
@@ -254,7 +293,7 @@ class DereferenceableExpr extends Expr {
|
||||
exists(ComparisonTest ct, ComparisonKind ck, Expr e | ct.getExpr() = result |
|
||||
ct.getAnArgument() = this and
|
||||
ct.getAnArgument() = e and
|
||||
e = any(NullValue nv | not nv.isNull()).getAnExpr() and
|
||||
e = any(NullValue nv | nv.isNonNull()).getAnExpr() and
|
||||
ck = ct.getComparisonKind() and
|
||||
this != e and
|
||||
isNull = false and
|
||||
@@ -363,7 +402,7 @@ class DereferenceableExpr extends Expr {
|
||||
v.isNull() and
|
||||
isNull = true
|
||||
) else (
|
||||
not v.isNull() and
|
||||
v.isNonNull() and
|
||||
isNull = false
|
||||
)
|
||||
)
|
||||
@@ -388,6 +427,113 @@ class DereferenceableExpr extends Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that evaluates to a collection. That is, an expression whose
|
||||
* (transitive, reflexive) base type is `IEnumerable`.
|
||||
*/
|
||||
class CollectionExpr extends Expr {
|
||||
CollectionExpr() {
|
||||
this.getType().(ValueOrRefType).getABaseType*() instanceof SystemCollectionsIEnumerableInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that computes the size of this collection. `lowerBound`
|
||||
* indicates whether the expression only computes a lower bound.
|
||||
*/
|
||||
private Expr getASizeExpr(boolean lowerBound) {
|
||||
lowerBound = false and
|
||||
result = any(PropertyRead pr |
|
||||
this = pr.getQualifier() and
|
||||
pr.getTarget() = any(SystemArrayClass x).getLengthProperty()
|
||||
)
|
||||
or
|
||||
lowerBound = false and
|
||||
result = any(PropertyRead pr |
|
||||
this = pr.getQualifier() and
|
||||
pr
|
||||
.getTarget()
|
||||
.overridesOrImplementsOrEquals(any(Property p |
|
||||
p.getSourceDeclaration() = any(SystemCollectionsGenericICollectionInterface x)
|
||||
.getCountProperty()
|
||||
))
|
||||
)
|
||||
or
|
||||
result = any(MethodCall mc |
|
||||
mc.getTarget().getSourceDeclaration() = any(SystemLinq::SystemLinqEnumerableClass x)
|
||||
.getACountMethod() and
|
||||
this = mc.getArgument(0) and
|
||||
if mc.getNumberOfArguments() = 1 then lowerBound = false else lowerBound = true
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getABooleanEmptinessCheck(BooleanValue v, boolean isEmpty) {
|
||||
exists(boolean branch | branch = v.getValue() |
|
||||
result = any(ComparisonTest ct |
|
||||
exists(boolean lowerBound |
|
||||
ct.getAnArgument() = this.getASizeExpr(lowerBound) and
|
||||
if isEmpty = true then lowerBound = false else any()
|
||||
|
|
||||
// x.Length == 0
|
||||
ct.getComparisonKind().isEquality() and
|
||||
ct.getAnArgument().getValue().toInt() = 0 and
|
||||
branch = isEmpty
|
||||
or
|
||||
// x.Length == k, k > 0
|
||||
ct.getComparisonKind().isEquality() and
|
||||
ct.getAnArgument().getValue().toInt() > 0 and
|
||||
branch = true and
|
||||
isEmpty = false
|
||||
or
|
||||
// x.Length != 0
|
||||
ct.getComparisonKind().isInequality() and
|
||||
ct.getAnArgument().getValue().toInt() = 0 and
|
||||
branch = isEmpty.booleanNot()
|
||||
or
|
||||
// x.Length != k, k != 0
|
||||
ct.getComparisonKind().isInequality() and
|
||||
ct.getAnArgument().getValue().toInt() != 0 and
|
||||
branch = false and
|
||||
isEmpty = false
|
||||
or
|
||||
// x.Length > k, k >= 0
|
||||
ct.getComparisonKind().isLessThan() and
|
||||
ct.getFirstArgument().getValue().toInt() >= 0 and
|
||||
branch = true and
|
||||
isEmpty = false
|
||||
or
|
||||
// x.Length >= k, k > 0
|
||||
ct.getComparisonKind().isLessThanEquals() and
|
||||
ct.getFirstArgument().getValue().toInt() > 0 and
|
||||
branch = true and
|
||||
isEmpty = false
|
||||
)
|
||||
).getExpr()
|
||||
or
|
||||
result = any(MethodCall mc |
|
||||
mc.getTarget().getSourceDeclaration() = any(SystemLinq::SystemLinqEnumerableClass x)
|
||||
.getAnAnyMethod() and
|
||||
this = mc.getArgument(0) and
|
||||
branch = isEmpty.booleanNot() and
|
||||
if branch = false then mc.getNumberOfArguments() = 1 else any()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that tests whether this expression is empty.
|
||||
*
|
||||
* If the returned expression has abstract value `v`, then this expression is
|
||||
* guaranteed to be empty if `isEmpty` is true, and non-empty if `isEmpty` is
|
||||
* false.
|
||||
*
|
||||
* For example, if the expression `x.Length != 0` evaluates to `true` then the
|
||||
* expression `x` is guaranteed to be non-empty.
|
||||
*/
|
||||
Expr getAnEmptinessCheck(AbstractValue v, boolean isEmpty) {
|
||||
result = this.getABooleanEmptinessCheck(v, isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that accesses/calls a declaration. */
|
||||
class AccessOrCallExpr extends Expr {
|
||||
private Declaration target;
|
||||
@@ -630,12 +776,12 @@ class GuardedDataFlowNode extends DataFlow::ExprNode {
|
||||
|
||||
/** An expression guarded by a `null` check. */
|
||||
class NullGuardedExpr extends GuardedExpr {
|
||||
NullGuardedExpr() { this.mustHaveValue(any(NullValue v | not v.isNull())) }
|
||||
NullGuardedExpr() { this.mustHaveValue(any(NullValue v | v.isNonNull())) }
|
||||
}
|
||||
|
||||
/** A data flow node guarded by a `null` check. */
|
||||
class NullGuardedDataFlowNode extends GuardedDataFlowNode {
|
||||
NullGuardedDataFlowNode() { this.mustHaveValue(any(NullValue v | not v.isNull())) }
|
||||
NullGuardedDataFlowNode() { this.mustHaveValue(any(NullValue v | v.isNonNull())) }
|
||||
}
|
||||
|
||||
/** INTERNAL: Do not use. */
|
||||
@@ -755,7 +901,7 @@ module Internal {
|
||||
bao.getAnOperand() = o and
|
||||
// The other operand must be provably non-null in order
|
||||
// for `only if` to hold
|
||||
o = any(NullValue nv | not nv.isNull()).getAnExpr() and
|
||||
o = any(NullValue nv | nv.isNonNull()).getAnExpr() and
|
||||
e != o
|
||||
)
|
||||
}
|
||||
@@ -834,7 +980,7 @@ module Internal {
|
||||
v.(NullValue).isNull()
|
||||
or
|
||||
a.getAssertMethod() instanceof AssertNonNullMethod and
|
||||
v = any(NullValue nv | not nv.isNull())
|
||||
v.(NullValue).isNonNull()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -871,7 +1017,7 @@ module Internal {
|
||||
}
|
||||
|
||||
/** Holds if pre-basic-block `bb` only is reached when guard `g` has abstract value `v`. */
|
||||
private predicate preControls(Guard g, PreBasicBlocks::PreBasicBlock bb, AbstractValue v) {
|
||||
predicate preControls(Guard g, PreBasicBlocks::PreBasicBlock bb, AbstractValue v) {
|
||||
exists(AbstractValue v0, Guard g0 | preControlsDirect(g0, bb, v0) |
|
||||
preImpliesSteps(g0, v0, g, v)
|
||||
)
|
||||
@@ -1257,25 +1403,39 @@ module Internal {
|
||||
nonNullValueImplied(def.getDefinition().getSource())
|
||||
}
|
||||
|
||||
private predicate emptyDef(PreSsa::Definition def) {
|
||||
emptyValue(def.getDefinition().getSource())
|
||||
}
|
||||
|
||||
private predicate nonEmptyDef(PreSsa::Definition def) {
|
||||
nonEmptyValue(def.getDefinition().getSource())
|
||||
}
|
||||
|
||||
cached
|
||||
private module CachedWithCFG {
|
||||
private import semmle.code.csharp.Caching
|
||||
|
||||
cached
|
||||
predicate isGuard(Expr e, AbstractValue val) {
|
||||
Stages::ControlFlowStage::forceCachingInSameStage() and
|
||||
e.getType() instanceof BoolType and
|
||||
not e instanceof BoolLiteral and
|
||||
not e instanceof SwitchCaseExpr and
|
||||
not e instanceof PatternExpr and
|
||||
val = TBooleanValue(_)
|
||||
or
|
||||
e instanceof DereferenceableExpr and
|
||||
val = TNullValue(_)
|
||||
or
|
||||
val.branch(_, _, e)
|
||||
or
|
||||
asserts(_, e, val)
|
||||
(
|
||||
e.getType() instanceof BoolType and
|
||||
not e instanceof BoolLiteral and
|
||||
not e instanceof SwitchCaseExpr and
|
||||
not e instanceof PatternExpr and
|
||||
val = TBooleanValue(_)
|
||||
or
|
||||
e instanceof DereferenceableExpr and
|
||||
val = TNullValue(_)
|
||||
or
|
||||
val.branch(_, _, e)
|
||||
or
|
||||
asserts(_, e, val)
|
||||
or
|
||||
e instanceof CollectionExpr and
|
||||
val = TEmptyCollectionValue(_)
|
||||
) and
|
||||
not e = any(ExprStmt es).getExpr() and
|
||||
not e = any(LocalVariableDeclStmt s).getAVariableDeclExpr()
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -1287,6 +1447,15 @@ module Internal {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate firstReadSameVarUniquePredecesssor(
|
||||
PreSsa::Definition def, AssignableRead read
|
||||
) {
|
||||
PreSsa::firstReadSameVar(def, read) and
|
||||
not exists(AssignableRead other | PreSsa::adjacentReadPairSameVar(other, read) |
|
||||
other != read
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the assumption that `g1` has abstract value `v1` implies that
|
||||
* `g2` has abstract value `v2`, using one step of reasoning. That is, the
|
||||
@@ -1373,6 +1542,13 @@ module Internal {
|
||||
(g1 != g2 or v1 != v2)
|
||||
)
|
||||
or
|
||||
exists(boolean isEmpty | g1 = g2.(CollectionExpr).getAnEmptinessCheck(v1, isEmpty) |
|
||||
v2 = any(EmptyCollectionValue ecv |
|
||||
if ecv.isEmpty() then isEmpty = true else isEmpty = false
|
||||
) and
|
||||
g1 != g2
|
||||
)
|
||||
or
|
||||
g1 instanceof DereferenceableExpr and
|
||||
g1 = getNullEquivParent(g2) and
|
||||
v1 instanceof NullValue and
|
||||
@@ -1380,7 +1556,7 @@ module Internal {
|
||||
or
|
||||
g1 instanceof DereferenceableExpr and
|
||||
g2 = getANullImplyingChild(g1) and
|
||||
v1 = any(NullValue nv | not nv.isNull()) and
|
||||
v1.(NullValue).isNonNull() and
|
||||
v2 = v1
|
||||
or
|
||||
g2 = g1.(AssignExpr).getRValue() and
|
||||
@@ -1395,10 +1571,12 @@ module Internal {
|
||||
isGuard(g1, v1) and
|
||||
v2 = v1.(NullValue)
|
||||
or
|
||||
exists(PreSsa::Definition def | def.getDefinition().getSource() = g2 |
|
||||
exists(PreSsa::Definition def |
|
||||
def.getDefinition().getSource() = g2 and
|
||||
g1 = def.getARead() and
|
||||
isGuard(g1, v1) and
|
||||
v2 = v1
|
||||
v2 = v1 and
|
||||
if v1.isReferentialProperty() then firstReadSameVarUniquePredecesssor(def, g1) else any()
|
||||
)
|
||||
or
|
||||
exists(PreSsa::Definition def, AbstractValue v |
|
||||
@@ -1449,6 +1627,63 @@ module Internal {
|
||||
forex(PreSsa::Definition u | u = def.getAnUltimateDefinition() | nonNullDef(u))
|
||||
).getARead()
|
||||
}
|
||||
|
||||
private predicate adjacentReadPairSameVarUniquePredecessor(
|
||||
AssignableRead read1, AssignableRead read2
|
||||
) {
|
||||
PreSsa::adjacentReadPairSameVar(read1, read2) and
|
||||
not exists(AssignableRead other |
|
||||
PreSsa::adjacentReadPairSameVar(other, read2) and
|
||||
other != read1 and
|
||||
other != read2
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate emptyValue(Expr e) {
|
||||
e.(ArrayCreation).getALengthArgument().getValue().toInt() = 0
|
||||
or
|
||||
e.(ArrayInitializer).hasNoElements()
|
||||
or
|
||||
exists(Expr mid | emptyValue(mid) |
|
||||
mid = e.(AssignExpr).getRValue()
|
||||
or
|
||||
mid = e.(Cast).getExpr()
|
||||
)
|
||||
or
|
||||
exists(PreSsa::Definition def | emptyDef(def) | firstReadSameVarUniquePredecesssor(def, e))
|
||||
or
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().getAnUltimateImplementee().getSourceDeclaration() = any(SystemCollectionsGenericICollectionInterface c
|
||||
).getClearMethod() and
|
||||
adjacentReadPairSameVarUniquePredecessor(mc.getQualifier(), e)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate nonEmptyValue(Expr e) {
|
||||
forex(Expr length | length = e.(ArrayCreation).getALengthArgument() |
|
||||
length.getValue().toInt() != 0
|
||||
)
|
||||
or
|
||||
e.(ArrayInitializer).getNumberOfElements() > 0
|
||||
or
|
||||
exists(Expr mid | nonEmptyValue(mid) |
|
||||
mid = e.(AssignExpr).getRValue()
|
||||
or
|
||||
mid = e.(Cast).getExpr()
|
||||
)
|
||||
or
|
||||
exists(PreSsa::Definition def | nonEmptyDef(def) |
|
||||
firstReadSameVarUniquePredecesssor(def, e)
|
||||
)
|
||||
or
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().getAnUltimateImplementee().getSourceDeclaration() = any(SystemCollectionsGenericICollectionInterface c
|
||||
).getAddMethod() and
|
||||
adjacentReadPairSameVarUniquePredecessor(mc.getQualifier(), e)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import CachedWithCFG
|
||||
@@ -1515,14 +1750,29 @@ module Internal {
|
||||
exists(ConditionOnExprComparisonConfig c | c.same(sub, guarded))
|
||||
}
|
||||
|
||||
private predicate adjacentReadPairSameVarUniquePredecessor(
|
||||
Ssa::Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2
|
||||
) {
|
||||
Ssa::Internal::adjacentReadPairSameVar(def, cfn1, cfn2) and
|
||||
not exists(ControlFlow::Node other |
|
||||
Ssa::Internal::adjacentReadPairSameVar(def, other, cfn2) and
|
||||
other != cfn1 and
|
||||
other != cfn2
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate isGuardedByExpr(
|
||||
AccessOrCallExpr guarded, Guard g, AccessOrCallExpr sub, AbstractValue v
|
||||
) {
|
||||
isGuardedByExpr1(guarded, g, sub, v) and
|
||||
sub = getAChildExprStar(g) and
|
||||
forall(Ssa::Definition def | def = sub.getAnSsaQualifier(_) |
|
||||
def = guarded.getAnSsaQualifier(_)
|
||||
forall(Ssa::Definition def, ControlFlow::Node subCfn | def = sub.getAnSsaQualifier(subCfn) |
|
||||
exists(ControlFlow::Node defCfn | def = guarded.getAnSsaQualifier(defCfn) |
|
||||
if v.isReferentialProperty()
|
||||
then adjacentReadPairSameVarUniquePredecessor(def, subCfn, defCfn)
|
||||
else any()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1550,7 +1800,20 @@ module Internal {
|
||||
) {
|
||||
isGuardedByNode1(guarded, g, sub, v) and
|
||||
sub = getAChildExprStar(g) and
|
||||
forall(Ssa::Definition def | def = sub.getAnSsaQualifier(_) | isGuardedByNode2(guarded, def))
|
||||
forall(Ssa::Definition def, ControlFlow::Node subCfn | def = sub.getAnSsaQualifier(subCfn) |
|
||||
isGuardedByNode2(guarded, def) and
|
||||
if v.isReferentialProperty()
|
||||
then adjacentReadPairSameVarUniquePredecessor(def, subCfn, guarded)
|
||||
else any()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate firstReadUniquePredecessor(Ssa::ExplicitDefinition def, ControlFlow::Node cfn) {
|
||||
exists(def.getAFirstReadAtNode(cfn)) and
|
||||
not exists(ControlFlow::Node other |
|
||||
Ssa::Internal::adjacentReadPairSameVar(def, other, cfn) and
|
||||
other != cfn
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1564,11 +1827,12 @@ module Internal {
|
||||
predicate impliesStep(Guard g1, AbstractValue v1, Guard g2, AbstractValue v2) {
|
||||
preImpliesStep(g1, v1, g2, v2)
|
||||
or
|
||||
forex(ControlFlow::Node cfn | cfn = g1.getAControlFlowNode() |
|
||||
forex(ControlFlow::Node cfn1 | cfn1 = g1.getAControlFlowNode() |
|
||||
exists(Ssa::ExplicitDefinition def | def.getADefinition().getSource() = g2 |
|
||||
g1 = def.getAReadAtNode(cfn) and
|
||||
g1 = def.getAReadAtNode(cfn1) and
|
||||
isGuard(g1, v1) and
|
||||
v2 = v1
|
||||
v2 = v1 and
|
||||
if v1.isReferentialProperty() then firstReadUniquePredecessor(def, cfn1) else any()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -54,6 +54,28 @@ private newtype TCompletion =
|
||||
exists(boolean b | inner = TBooleanCompletion(b) and outer = TBooleanCompletion(b.booleanNot()))
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate completionIsValidForStmt(Stmt s, Completion c) {
|
||||
s instanceof BreakStmt and
|
||||
c = TBreakCompletion()
|
||||
or
|
||||
s instanceof ContinueStmt and
|
||||
c = TContinueCompletion()
|
||||
or
|
||||
s instanceof GotoStmt and
|
||||
c = TGotoCompletion(s.(GotoStmt).getLabel())
|
||||
or
|
||||
s instanceof ReturnStmt and
|
||||
c = TReturnCompletion()
|
||||
or
|
||||
s instanceof YieldBreakStmt and
|
||||
// `yield break` behaves like a return statement
|
||||
c = TReturnCompletion()
|
||||
or
|
||||
mustHaveEmptinessCompletion(s) and
|
||||
c = TEmptinessCompletion(_)
|
||||
}
|
||||
|
||||
/**
|
||||
* A completion of a statement or an expression.
|
||||
*/
|
||||
@@ -68,76 +90,59 @@ class Completion extends TCompletion {
|
||||
* otherwise it is a normal non-Boolean completion.
|
||||
*/
|
||||
predicate isValidFor(ControlFlowElement cfe) {
|
||||
if cfe instanceof NonReturningCall
|
||||
then this = cfe.(NonReturningCall).getACompletion()
|
||||
else (
|
||||
this = TThrowCompletion(cfe.(TriedControlFlowElement).getAThrownException())
|
||||
cfe instanceof NonReturningCall and
|
||||
this = cfe.(NonReturningCall).getACompletion()
|
||||
or
|
||||
this = TThrowCompletion(cfe.(TriedControlFlowElement).getAThrownException())
|
||||
or
|
||||
cfe instanceof ThrowElement and
|
||||
this = TThrowCompletion(cfe.(ThrowElement).getThrownExceptionType())
|
||||
or
|
||||
completionIsValidForStmt(cfe, this)
|
||||
or
|
||||
mustHaveBooleanCompletion(cfe) and
|
||||
(
|
||||
exists(boolean value | isBooleanConstant(cfe, value) | this = TBooleanCompletion(value))
|
||||
or
|
||||
cfe instanceof ThrowElement and
|
||||
this = TThrowCompletion(cfe.(ThrowElement).getThrownExceptionType())
|
||||
or
|
||||
cfe instanceof BreakStmt and
|
||||
this = TBreakCompletion()
|
||||
or
|
||||
cfe instanceof ContinueStmt and
|
||||
this = TContinueCompletion()
|
||||
or
|
||||
cfe instanceof GotoStmt and
|
||||
this = TGotoCompletion(cfe.(GotoStmt).getLabel())
|
||||
or
|
||||
cfe instanceof ReturnStmt and
|
||||
this = TReturnCompletion()
|
||||
or
|
||||
cfe instanceof YieldBreakStmt and
|
||||
// `yield break` behaves like a return statement
|
||||
this = TReturnCompletion()
|
||||
or
|
||||
mustHaveBooleanCompletion(cfe) and
|
||||
(
|
||||
exists(boolean value | isBooleanConstant(cfe, value) | this = TBooleanCompletion(value))
|
||||
or
|
||||
not isBooleanConstant(cfe, _) and
|
||||
this = TBooleanCompletion(_)
|
||||
or
|
||||
// Corner case: In `if (x ?? y) { ... }`, `x` must have both a `true`
|
||||
// completion, a `false` completion, and a `null` completion (but not a
|
||||
// non-`null` completion)
|
||||
mustHaveNullnessCompletion(cfe) and
|
||||
this = TNullnessCompletion(true)
|
||||
)
|
||||
not isBooleanConstant(cfe, _) and
|
||||
this = TBooleanCompletion(_)
|
||||
or
|
||||
// Corner case: In `if (x ?? y) { ... }`, `x` must have both a `true`
|
||||
// completion, a `false` completion, and a `null` completion (but not a
|
||||
// non-`null` completion)
|
||||
mustHaveNullnessCompletion(cfe) and
|
||||
not mustHaveBooleanCompletion(cfe) and
|
||||
(
|
||||
exists(boolean value | isNullnessConstant(cfe, value) | this = TNullnessCompletion(value))
|
||||
or
|
||||
not isNullnessConstant(cfe, _) and
|
||||
this = TNullnessCompletion(_)
|
||||
)
|
||||
or
|
||||
mustHaveMatchingCompletion(cfe) and
|
||||
(
|
||||
exists(boolean value | isMatchingConstant(cfe, value) | this = TMatchingCompletion(value))
|
||||
or
|
||||
not isMatchingConstant(cfe, _) and
|
||||
this = TMatchingCompletion(_)
|
||||
)
|
||||
or
|
||||
mustHaveEmptinessCompletion(cfe) and
|
||||
this = TEmptinessCompletion(_)
|
||||
or
|
||||
not cfe instanceof ThrowElement and
|
||||
not cfe instanceof BreakStmt and
|
||||
not cfe instanceof ContinueStmt and
|
||||
not cfe instanceof GotoStmt and
|
||||
not cfe instanceof ReturnStmt and
|
||||
not cfe instanceof YieldBreakStmt and
|
||||
not mustHaveBooleanCompletion(cfe) and
|
||||
not mustHaveNullnessCompletion(cfe) and
|
||||
not mustHaveMatchingCompletion(cfe) and
|
||||
not mustHaveEmptinessCompletion(cfe) and
|
||||
this = TNormalCompletion()
|
||||
this = TNullnessCompletion(true)
|
||||
)
|
||||
or
|
||||
mustHaveNullnessCompletion(cfe) and
|
||||
not mustHaveBooleanCompletion(cfe) and
|
||||
(
|
||||
exists(boolean value | isNullnessConstant(cfe, value) | this = TNullnessCompletion(value))
|
||||
or
|
||||
not isNullnessConstant(cfe, _) and
|
||||
this = TNullnessCompletion(_)
|
||||
)
|
||||
or
|
||||
mustHaveMatchingCompletion(cfe) and
|
||||
(
|
||||
exists(boolean value | isMatchingConstant(cfe, value) | this = TMatchingCompletion(value))
|
||||
or
|
||||
not isMatchingConstant(cfe, _) and
|
||||
this = TMatchingCompletion(_)
|
||||
)
|
||||
or
|
||||
not cfe instanceof NonReturningCall and
|
||||
not cfe instanceof ThrowElement and
|
||||
not cfe instanceof BreakStmt and
|
||||
not cfe instanceof ContinueStmt and
|
||||
not cfe instanceof GotoStmt and
|
||||
not cfe instanceof ReturnStmt and
|
||||
not cfe instanceof YieldBreakStmt and
|
||||
not mustHaveBooleanCompletion(cfe) and
|
||||
not mustHaveNullnessCompletion(cfe) and
|
||||
not mustHaveMatchingCompletion(cfe) and
|
||||
not mustHaveEmptinessCompletion(cfe) and
|
||||
this = TNormalCompletion()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,7 +269,10 @@ private predicate assemblyCompiledWithCoreLib(Assembly a, CoreLib core) {
|
||||
private class TriedControlFlowElement extends ControlFlowElement {
|
||||
TryStmt try;
|
||||
|
||||
TriedControlFlowElement() { this = try.getATriedElement() }
|
||||
TriedControlFlowElement() {
|
||||
this = try.getATriedElement() and
|
||||
not this instanceof NonReturningCall
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an exception class that is potentially thrown by this element, if any.
|
||||
@@ -372,7 +380,8 @@ private predicate invalidCastCandidate(CastExpr ce) {
|
||||
*/
|
||||
private predicate mustHaveBooleanCompletion(Expr e) {
|
||||
inBooleanContext(e, _) and
|
||||
not inBooleanContext(e.getAChildExpr(), true)
|
||||
not inBooleanContext(e.getAChildExpr(), true) and
|
||||
not e instanceof NonReturningCall
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,7 +451,8 @@ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent)
|
||||
*/
|
||||
private predicate mustHaveNullnessCompletion(Expr e) {
|
||||
inNullnessContext(e, _) and
|
||||
not inNullnessContext(e.getAChildExpr(), true)
|
||||
not inNullnessContext(e.getAChildExpr(), true) and
|
||||
not e instanceof NonReturningCall
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,8 @@ private module Cached {
|
||||
TInitializerSplitKind() or
|
||||
TFinallySplitKind() or
|
||||
TExceptionHandlerSplitKind() or
|
||||
TBooleanSplitKind(BooleanSplitting::BooleanSplitSubKind kind) { kind.startsSplit(_) }
|
||||
TBooleanSplitKind(BooleanSplitting::BooleanSplitSubKind kind) { kind.startsSplit(_) } or
|
||||
TLoopUnrollingSplitKind(LoopUnrollingSplitting::UnrollableLoopStmt loop)
|
||||
|
||||
cached
|
||||
newtype TSplit =
|
||||
@@ -39,7 +40,8 @@ private module Cached {
|
||||
TBooleanSplit(BooleanSplitting::BooleanSplitSubKind kind, boolean branch) {
|
||||
kind.startsSplit(_) and
|
||||
(branch = true or branch = false)
|
||||
}
|
||||
} or
|
||||
TLoopUnrollingSplit(LoopUnrollingSplitting::UnrollableLoopStmt loop)
|
||||
|
||||
cached
|
||||
newtype TSplits =
|
||||
@@ -1023,6 +1025,153 @@ module BooleanSplitting {
|
||||
}
|
||||
}
|
||||
|
||||
module LoopUnrollingSplitting {
|
||||
private import semmle.code.csharp.controlflow.Guards as Guards
|
||||
private import PreBasicBlocks
|
||||
private import PreSsa
|
||||
|
||||
/** Holds if `ce` is guarded by a (non-)empty check, as specified by `v`. */
|
||||
private predicate emptinessGuarded(
|
||||
Guards::Guard g, Guards::CollectionExpr ce, Guards::AbstractValues::EmptyCollectionValue v
|
||||
) {
|
||||
exists(PreBasicBlock bb | Guards::Internal::preControls(g, bb, v) |
|
||||
PreSsa::adjacentReadPairSameVar(g, ce) and
|
||||
bb.getAnElement() = ce
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A loop where the body is guaranteed to be executed at least once, and
|
||||
* can therefore be unrolled in the control flow graph.
|
||||
*/
|
||||
abstract class UnrollableLoopStmt extends LoopStmt {
|
||||
/** Holds if the step `pred --c--> succ` should start loop unrolling. */
|
||||
abstract predicate startUnroll(ControlFlowElement pred, ControlFlowElement succ, Completion c);
|
||||
|
||||
/** Holds if the step `pred --c--> succ` should stop loop unrolling. */
|
||||
abstract predicate stopUnroll(ControlFlowElement pred, ControlFlowElement succ, Completion c);
|
||||
|
||||
/**
|
||||
* Holds if any step `pred --c--> _` should be pruned from the unrolled loop
|
||||
* (the loop condition evaluating to `false`).
|
||||
*/
|
||||
abstract predicate pruneLoopCondition(ControlFlowElement pred, ConditionalCompletion c);
|
||||
}
|
||||
|
||||
private class UnrollableForeachStmt extends UnrollableLoopStmt, ForeachStmt {
|
||||
UnrollableForeachStmt() {
|
||||
exists(Guards::AbstractValues::EmptyCollectionValue v | v.isNonEmpty() |
|
||||
emptinessGuarded(_, this.getIterableExpr(), v)
|
||||
or
|
||||
this.getIterableExpr() = v.getAnExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate startUnroll(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
pred = last(this.getIterableExpr(), c) and
|
||||
succ = this
|
||||
}
|
||||
|
||||
override predicate stopUnroll(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
pred = this and
|
||||
succ = succ(pred, c)
|
||||
}
|
||||
|
||||
override predicate pruneLoopCondition(ControlFlowElement pred, ConditionalCompletion c) {
|
||||
pred = this and
|
||||
c.(EmptinessCompletion).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A split for loops where the body is guaranteed to be executed at least once, and
|
||||
* can therefore be unrolled in the control flow graph. For example, in
|
||||
*
|
||||
* ```
|
||||
* void M(string[] args)
|
||||
* {
|
||||
* if (args.Length == 0)
|
||||
* return;
|
||||
* foreach (var arg in args)
|
||||
* System.Console.WriteLine(args);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* the `foreach` loop is guaranteed to be executed at least once, as a result of the
|
||||
* `args.Length == 0` check.
|
||||
*/
|
||||
class LoopUnrollingSplitImpl extends SplitImpl, TLoopUnrollingSplit {
|
||||
UnrollableLoopStmt loop;
|
||||
|
||||
LoopUnrollingSplitImpl() { this = TLoopUnrollingSplit(loop) }
|
||||
|
||||
override string toString() {
|
||||
result = "unroll (line " + loop.getLocation().getStartLine() + ")"
|
||||
}
|
||||
}
|
||||
|
||||
private int getListOrder(UnrollableLoopStmt loop) {
|
||||
exists(Callable c, int r | c = loop.getEnclosingCallable() |
|
||||
result = r + BooleanSplitting::getNextListOrder() - 1 and
|
||||
loop = rank[r](UnrollableLoopStmt loop0 |
|
||||
loop0.getEnclosingCallable() = c
|
||||
|
|
||||
loop0 order by loop0.getLocation().getStartLine(), loop0.getLocation().getStartColumn()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
int getNextListOrder() {
|
||||
result = max(int i | i = getListOrder(_) + 1 or i = BooleanSplitting::getNextListOrder())
|
||||
}
|
||||
|
||||
private class LoopUnrollingSplitKind extends SplitKind, TLoopUnrollingSplitKind {
|
||||
private UnrollableLoopStmt loop;
|
||||
|
||||
LoopUnrollingSplitKind() { this = TLoopUnrollingSplitKind(loop) }
|
||||
|
||||
override int getListOrder() { result = getListOrder(loop) }
|
||||
|
||||
override string toString() { result = "Unroll" }
|
||||
}
|
||||
|
||||
private class LoopUnrollingSplitInternal extends SplitInternal, LoopUnrollingSplitImpl {
|
||||
override LoopUnrollingSplitKind getKind() { result = TLoopUnrollingSplitKind(loop) }
|
||||
|
||||
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
loop.startUnroll(pred, succ, c)
|
||||
}
|
||||
|
||||
override predicate hasEntry(Callable pred, ControlFlowElement succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if this split applies to control flow element `pred`, where `pred`
|
||||
* is a valid predecessor.
|
||||
*/
|
||||
private predicate appliesToPredecessor(ControlFlowElement pred, Completion c) {
|
||||
this.appliesTo(pred) and
|
||||
(exists(succ(pred, c)) or exists(succExit(pred, c))) and
|
||||
not loop.pruneLoopCondition(pred, c)
|
||||
}
|
||||
|
||||
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
this.appliesToPredecessor(pred, c) and
|
||||
loop.stopUnroll(pred, succ, c)
|
||||
}
|
||||
|
||||
override Callable hasExit(ControlFlowElement pred, Completion c) {
|
||||
this.appliesToPredecessor(pred, c) and
|
||||
result = succExit(pred, c)
|
||||
}
|
||||
|
||||
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
this.appliesToPredecessor(pred, c) and
|
||||
succ = succ(pred, c) and
|
||||
not loop.stopUnroll(pred, succ, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of control flow node splits. The set is represented by a list of splits,
|
||||
* ordered by ascending rank.
|
||||
|
||||
@@ -143,7 +143,7 @@ private predicate ensureNotNullAt(BasicBlock bb, int i, Ssa::Definition def) {
|
||||
G::Internal::asserts(bb.getNode(i).getElement(), e, v)
|
||||
|
|
||||
exprImpliesSsaDef(e, v, def, nv) and
|
||||
not nv.isNull()
|
||||
nv.isNonNull()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ private predicate defNullImpliesStep(
|
||||
bb1.getLastNode() = getANullCheck(def1, s, nv).getAControlFlowNode()
|
||||
|
|
||||
bb2 = bb1.getASuccessorByType(s) and
|
||||
not nv.isNull()
|
||||
nv.isNonNull()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,13 @@ module BaseSsa {
|
||||
private import ControlFlow
|
||||
private import AssignableDefinitions
|
||||
|
||||
pragma[noinline]
|
||||
Callable getAnAssigningCallable(LocalScopeVariable v) {
|
||||
result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable()
|
||||
}
|
||||
|
||||
private class SimpleLocalScopeVariable extends LocalScopeVariable {
|
||||
SimpleLocalScopeVariable() {
|
||||
not exists(AssignableDefinition def1, AssignableDefinition def2 |
|
||||
def1.getTarget() = this and
|
||||
def2.getTarget() = this and
|
||||
def1.getEnclosingCallable() != def2.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
SimpleLocalScopeVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1260,7 +1260,7 @@ abstract private class AccessPath extends TAccessPath {
|
||||
|
||||
private class AccessPathNil extends AccessPath, TNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
|
||||
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
@@ -1647,6 +1647,11 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,6 +54,9 @@ class SystemActionTDelegateType extends SystemUnboundGenericDelegateType {
|
||||
/** `System.Array` class. */
|
||||
class SystemArrayClass extends SystemClass {
|
||||
SystemArrayClass() { this.hasName("Array") }
|
||||
|
||||
/** Gets the `Length` property. */
|
||||
Property getLengthProperty() { result = this.getProperty("Length") }
|
||||
}
|
||||
|
||||
/** `System.Attribute` class. */
|
||||
|
||||
@@ -18,4 +18,15 @@ module SystemLinq {
|
||||
class Class extends csharp::Class {
|
||||
Class() { this.getNamespace() instanceof Namespace }
|
||||
}
|
||||
|
||||
/** The `System.Linq.Enumerable` class. */
|
||||
class SystemLinqEnumerableClass extends Class {
|
||||
SystemLinqEnumerableClass() { this.hasName("Enumerable") }
|
||||
|
||||
/** Gets a `Count()` method. */
|
||||
csharp::ExtensionMethod getACountMethod() { result = this.getAMethod("Count") }
|
||||
|
||||
/** Gets an `Any()` method. */
|
||||
csharp::ExtensionMethod getAnAnyMethod() { result = this.getAMethod("Any") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,13 @@ class SystemCollectionsGenericUnboundGenericInterface extends UnboundGenericInte
|
||||
}
|
||||
}
|
||||
|
||||
/** An unbound generic class in the `System.Collections.Generic` namespace. */
|
||||
class SystemCollectionsGenericUnboundGenericClass extends UnboundGenericClass {
|
||||
SystemCollectionsGenericUnboundGenericClass() {
|
||||
this.getNamespace() instanceof SystemCollectionsGenericNamespace
|
||||
}
|
||||
}
|
||||
|
||||
/** An unbound generic struct in the `System.Collections.Generic` namespace. */
|
||||
class SystemCollectionsGenericUnboundGenericStruct extends UnboundGenericStruct {
|
||||
SystemCollectionsGenericUnboundGenericStruct() {
|
||||
@@ -86,6 +93,14 @@ class SystemCollectionsGenericIListTInterface extends SystemCollectionsGenericUn
|
||||
}
|
||||
}
|
||||
|
||||
/** The `System.Collections.Generic.List<T>` class. */
|
||||
class SystemCollectionsGenericListClass extends SystemCollectionsGenericUnboundGenericClass {
|
||||
SystemCollectionsGenericListClass() {
|
||||
this.hasName("List<>") and
|
||||
this.getNumberOfTypeParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/** The `System.Collections.Generic.KeyValuePair<TKey, TValue>` structure. */
|
||||
class SystemCollectionsGenericKeyValuePairStruct extends SystemCollectionsGenericUnboundGenericStruct {
|
||||
SystemCollectionsGenericKeyValuePairStruct() {
|
||||
@@ -111,4 +126,13 @@ class SystemCollectionsGenericKeyValuePairStruct extends SystemCollectionsGeneri
|
||||
/** The `System.Collections.Generic.ICollection<>` interface. */
|
||||
class SystemCollectionsGenericICollectionInterface extends SystemCollectionsGenericUnboundGenericInterface {
|
||||
SystemCollectionsGenericICollectionInterface() { this.hasName("ICollection<>") }
|
||||
|
||||
/** Gets the `Count` property. */
|
||||
Property getCountProperty() { result = this.getProperty("Count") }
|
||||
|
||||
/** Gets the `Clear` method. */
|
||||
Method getClearMethod() { result = this.getAMethod("Clear") }
|
||||
|
||||
/** Gets the `Add` method. */
|
||||
Method getAddMethod() { result = this.getAMethod("Add") }
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ private module Cached {
|
||||
exists(TranslatedElement bodyOrUpdate |
|
||||
bodyOrUpdate = s.getBody()
|
||||
or
|
||||
bodyOrUpdate = s.getUpdate()
|
||||
bodyOrUpdate = s.getUpdate(_)
|
||||
|
|
||||
inLoop = bodyOrUpdate.getAChild*()
|
||||
) and
|
||||
|
||||
@@ -4,13 +4,14 @@ private import semmle.code.csharp.ir.implementation.internal.OperandTag
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedInitialization
|
||||
private import semmle.code.csharp.ir.Util
|
||||
private import semmle.code.csharp.ir.implementation.raw.internal.common.TranslatedCallBase
|
||||
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
|
||||
|
||||
/**
|
||||
* The IR translation of a call to a function. The function can be a normal function
|
||||
* (ie. `MethodCall`) or a constructor call (ie. `ObjectCreation`). Notice that the
|
||||
* (e.g. `MethodCall`) or a constructor call (e.g. `ObjectCreation`). Notice that the
|
||||
* AST generated translated calls are tied to an expression (unlike compiler generated ones,
|
||||
* which can be attached to either a statement or an expression).
|
||||
*/
|
||||
@@ -50,7 +51,13 @@ class TranslatedFunctionCall extends TranslatedNonConstantExpr, TranslatedCall {
|
||||
result = getTranslatedExpr(expr.(QualifiableExpr).getQualifier())
|
||||
}
|
||||
|
||||
override Instruction getQualifierResult() { result = this.getQualifier().getResult() }
|
||||
override Instruction getQualifierResult() {
|
||||
// since `ElementInitializer`s do not have a qualifier, the qualifier's result is retrieved
|
||||
// from the enclosing initialization context
|
||||
if expr.getParent() instanceof CollectionInitializer
|
||||
then result = getTranslatedExpr(expr.getParent()).(InitializationContext).getTargetAddress()
|
||||
else result = this.getQualifier().getResult()
|
||||
}
|
||||
|
||||
override Type getCallResultType() { result = expr.getTarget().getReturnType() }
|
||||
|
||||
|
||||
@@ -169,6 +169,11 @@ newtype TTranslatedElement =
|
||||
not isNativeCondition(expr) and
|
||||
not isFlexibleCondition(expr)
|
||||
} or
|
||||
// A creation expression
|
||||
TTranslatedCreationExpr(Expr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
(expr instanceof ObjectCreation or expr instanceof DelegateCreation)
|
||||
} or
|
||||
// A separate element to handle the lvalue-to-rvalue conversion step of an
|
||||
// expression.
|
||||
TTranslatedLoad(Expr expr) {
|
||||
@@ -219,32 +224,21 @@ newtype TTranslatedElement =
|
||||
// we deal with all the types of initialization separately.
|
||||
// First only simple local variable initialization (ie. `int x = 0`)
|
||||
exists(LocalVariableDeclAndInitExpr lvInit |
|
||||
lvInit.getInitializer() = expr and
|
||||
not expr instanceof ArrayCreation and
|
||||
not expr instanceof ObjectCreation and
|
||||
not expr instanceof DelegateCreation
|
||||
lvInit.getInitializer() = expr
|
||||
)
|
||||
or
|
||||
// Then treat more complex ones
|
||||
expr instanceof ObjectCreation
|
||||
or
|
||||
expr instanceof DelegateCreation
|
||||
or
|
||||
expr instanceof ArrayInitializer
|
||||
or
|
||||
expr instanceof ObjectInitializer
|
||||
or
|
||||
expr = any(ThrowExpr throw).getExpr()
|
||||
expr = any(ThrowElement throwElement).getExpr()
|
||||
or
|
||||
expr = any(CollectionInitializer colInit).getAnElementInitializer()
|
||||
or
|
||||
expr = any(ReturnStmt returnStmt).getExpr()
|
||||
or
|
||||
expr = any(ArrayInitializer arrInit).getAnElement()
|
||||
or
|
||||
expr = any(LambdaExpr lambda).getSourceDeclaration()
|
||||
or
|
||||
expr = any(AnonymousMethodExpr anonMethExpr).getSourceDeclaration()
|
||||
)
|
||||
} or
|
||||
// The initialization of an array element via a member of an initializer list.
|
||||
|
||||
@@ -24,7 +24,11 @@ private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
|
||||
*/
|
||||
TranslatedExpr getTranslatedExpr(Expr expr) {
|
||||
result.getExpr() = expr and
|
||||
result.producesExprResult()
|
||||
result.producesExprResult() and
|
||||
// When a constructor call is needed, we fetch it manually.
|
||||
// This is because of how we translate object creations: the translated expression
|
||||
// and the translated constructor call are attached to the same element.
|
||||
(expr instanceof ObjectCreation implies not result instanceof TranslatedConstructorCall)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,11 +485,7 @@ class TranslatedObjectInitializerExpr extends TranslatedNonConstantExpr, Initial
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(AssignExpr assign |
|
||||
result = getTranslatedExpr(expr.getChild(id)) and
|
||||
expr.getAChild() = assign and
|
||||
assign.getIndex() = id
|
||||
)
|
||||
result = getTranslatedExpr(expr.getMemberInitializer(id))
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
@@ -499,9 +499,57 @@ class TranslatedObjectInitializerExpr extends TranslatedNonConstantExpr, Initial
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() { result = this.getParent().getInstruction(NewObjTag()) }
|
||||
override Instruction getTargetAddress() {
|
||||
// The target address is the address of the newly allocated object,
|
||||
// which can be retrieved from the parent `TranslatedObjectCreation`.
|
||||
result = this.getParent().getInstruction(NewObjTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { none() }
|
||||
override Type getTargetType() {
|
||||
result = this.getParent().getInstruction(NewObjTag()).getResultType()
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedCollectionInitializer extends TranslatedNonConstantExpr, InitializationContext {
|
||||
override CollectionInitializer expr;
|
||||
|
||||
override Instruction getResult() { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getChild(0).getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = getTranslatedExpr(expr.getElementInitializer(id))
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
(
|
||||
result = this.getChild(index + 1).getFirstInstruction()
|
||||
or
|
||||
not exists(this.getChild(index + 1)) and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
// The target address is the address of the newly allocated object,
|
||||
// which can be retrieved from the parent `TranslatedObjectCreation`.
|
||||
result = this.getParent().getInstruction(NewObjTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() {
|
||||
result = this.getParent().getInstruction(NewObjTag()).getResultType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1918,3 +1966,88 @@ class TranslatedDelegateCall extends TranslatedNonConstantExpr {
|
||||
result = DelegateElements::getInvoke(expr)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of creation expression. Can be the translation of an
|
||||
* `ObjectCreation` or a `DelegateCreation`.
|
||||
* The `NewObj` instruction denotes the fact that during initialization a new
|
||||
* object is allocated, which is then initialized by the constructor.
|
||||
*/
|
||||
abstract class TranslatedCreation extends TranslatedCoreExpr, TTranslatedCreationExpr,
|
||||
ConstructorCallContext {
|
||||
TranslatedCreation() { this = TTranslatedCreationExpr(expr) }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getConstructorCall()
|
||||
or
|
||||
id = 1 and result = this.getInitializerExpr()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
// Instruction that allocated space for a new object,
|
||||
// and returns its address
|
||||
tag = NewObjTag() and
|
||||
opcode instanceof Opcode::NewObj and
|
||||
resultType = expr.getType() and
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = this.getInstruction(NewObjTag()) }
|
||||
|
||||
override Instruction getResult() { result = getInstruction(NewObjTag()) }
|
||||
|
||||
override Instruction getReceiver() { result = getInstruction(NewObjTag()) }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = NewObjTag() and
|
||||
result = this.getConstructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
(
|
||||
child = this.getConstructorCall() and
|
||||
if exists(this.getInitializerExpr())
|
||||
then result = this.getInitializerExpr().getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
or
|
||||
child = this.getInitializerExpr() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
abstract TranslatedElement getConstructorCall();
|
||||
|
||||
abstract TranslatedExpr getInitializerExpr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of an `ObjectCreation`.
|
||||
*/
|
||||
class TranslatedObjectCreation extends TranslatedCreation {
|
||||
override ObjectCreation expr;
|
||||
|
||||
override TranslatedExpr getInitializerExpr() { result = getTranslatedExpr(expr.getInitializer()) }
|
||||
|
||||
override TranslatedConstructorCall getConstructorCall() {
|
||||
// Since calls are also expressions, we can't
|
||||
// use the predicate getTranslatedExpr (since that would
|
||||
// also return `this`).
|
||||
result.getAST() = this.getAST()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of a `DelegateCreation`.
|
||||
*/
|
||||
class TranslatedDelegateCreation extends TranslatedCreation {
|
||||
override DelegateCreation expr;
|
||||
|
||||
override TranslatedExpr getInitializerExpr() { none() }
|
||||
|
||||
override TranslatedElement getConstructorCall() {
|
||||
result = DelegateElements::getConstructor(expr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,13 +123,9 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization {
|
||||
*/
|
||||
class TranslatedDirectInitialization extends TranslatedInitialization {
|
||||
TranslatedDirectInitialization() {
|
||||
// TODO: Make sure this is complete and correct
|
||||
not expr instanceof ArrayInitializer and
|
||||
not expr instanceof ObjectInitializer and
|
||||
not expr instanceof DelegateCreation and
|
||||
not expr instanceof CollectionInitializer and
|
||||
not expr instanceof ObjectCreation and
|
||||
not expr instanceof StringLiteral
|
||||
not expr instanceof CollectionInitializer
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() }
|
||||
@@ -145,64 +141,6 @@ class TranslatedDirectInitialization extends TranslatedInitialization {
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = this.getContext().getTargetType() and
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInitializer().getResult()
|
||||
)
|
||||
}
|
||||
|
||||
TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of an initialization from a constructor.
|
||||
* The `NewObj` instruction denotes the fact that during initialization a new
|
||||
* object of type `expr.getType()` is allocated, which is then initialized by the
|
||||
* constructor.
|
||||
*/
|
||||
class TranslatedObjectInitialization extends TranslatedInitialization, ConstructorCallContext {
|
||||
override ObjectCreation expr;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getConstructorCall()
|
||||
or
|
||||
id = 1 and result = this.getInitializerExpr()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
// Instruction that allocated space for a new object,
|
||||
// and returns its address
|
||||
tag = NewObjTag() and
|
||||
opcode instanceof Opcode::NewObj and
|
||||
resultType = expr.getType() and
|
||||
isLValue = false
|
||||
or
|
||||
// Store op used to assign the variable that
|
||||
// is initialized the address of the newly allocated
|
||||
// object
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = expr.getType() and
|
||||
isLValue = false
|
||||
or
|
||||
needsConversion() and
|
||||
tag = AssignmentConvertRightTag() and
|
||||
@@ -214,39 +152,22 @@ class TranslatedObjectInitialization extends TranslatedInitialization, Construct
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = this.getInstruction(NewObjTag()) }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = NewObjTag() and
|
||||
result = this.getConstructorCall().getFirstInstruction()
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
or
|
||||
tag = AssignmentConvertRightTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
)
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
needsConversion() and
|
||||
tag = AssignmentConvertRightTag() and
|
||||
result = getInstruction(InitializerStoreTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
(
|
||||
child = this.getConstructorCall() and
|
||||
if exists(this.getInitializerExpr())
|
||||
then result = this.getInitializerExpr().getFirstInstruction()
|
||||
else
|
||||
if this.needsConversion()
|
||||
then result = this.getInstruction(AssignmentConvertRightTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
)
|
||||
or
|
||||
(
|
||||
child = this.getInitializerExpr() and
|
||||
if this.needsConversion()
|
||||
then result = this.getInstruction(AssignmentConvertRightTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
)
|
||||
child = this.getInitializer() and
|
||||
if this.needsConversion()
|
||||
then result = this.getInstruction(AssignmentConvertRightTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
@@ -256,33 +177,28 @@ class TranslatedObjectInitialization extends TranslatedInitialization, Construct
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
or
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
if needsConversion()
|
||||
then result = this.getInstruction(AssignmentConvertRightTag())
|
||||
else result = this.getInstruction(NewObjTag())
|
||||
result = this.getInitializer().getResult()
|
||||
)
|
||||
)
|
||||
or
|
||||
tag = AssignmentConvertRightTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = this.getInitializer().getResult()
|
||||
or
|
||||
tag = AssignmentConvertRightTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = this.getInstruction(NewObjTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getConstructorCall() { result = getTranslatedExpr(expr) }
|
||||
|
||||
private TranslatedExpr getInitializerExpr() { result = getTranslatedExpr(expr.getInitializer()) }
|
||||
|
||||
override Instruction getReceiver() {
|
||||
// The newly allocated object will be the target of the constructor call
|
||||
result = this.getInstruction(NewObjTag())
|
||||
}
|
||||
TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
|
||||
|
||||
private predicate needsConversion() { expr.getType() != this.getContext().getTargetType() }
|
||||
}
|
||||
|
||||
//private string getZeroValue(Type type) {
|
||||
// if type instanceof FloatingPointType then result = "0.0" else result = "0"
|
||||
//}
|
||||
/**
|
||||
* Represents the IR translation of the initialization of an array element from
|
||||
* an element of an initializer list.
|
||||
@@ -424,7 +340,7 @@ class TranslatedConstructorInitializer extends TranslatedConstructorCallFromCons
|
||||
TTranslatedConstructorInitializer {
|
||||
TranslatedConstructorInitializer() { this = TTranslatedConstructorInitializer(call) }
|
||||
|
||||
override string toString() { result = "constuructor init: " + call.toString() }
|
||||
override string toString() { result = "constructor init: " + call.toString() }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if needsConversion()
|
||||
@@ -472,58 +388,3 @@ class TranslatedConstructorInitializer extends TranslatedConstructorCallFromCons
|
||||
derivedClass = this.getFunction().getDeclaringType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of a delegate creation.
|
||||
*/
|
||||
class TranslatedDelegateCreation extends TranslatedInitialization, ConstructorCallContext {
|
||||
override DelegateCreation expr;
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getConstructorCall() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
tag = NewObjTag() and
|
||||
opcode instanceof Opcode::NewObj and
|
||||
resultType = expr.getType() and
|
||||
isLValue = false
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = expr.getType() and
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(NewObjTag()) }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = NewObjTag() and
|
||||
result = getConstructorCall().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getConstructorCall() and
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(NewObjTag())
|
||||
)
|
||||
}
|
||||
|
||||
private TranslatedElement getConstructorCall() { result = DelegateElements::getConstructor(expr) }
|
||||
|
||||
override Instruction getReceiver() { result = getInstruction(NewObjTag()) }
|
||||
}
|
||||
|
||||
@@ -651,43 +651,68 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getDeclAndInit()
|
||||
initializerIndex(id) and result = this.getDeclAndInit(id)
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
result = this.getUpdate(updateIndex(id))
|
||||
or
|
||||
id = 2 and result = this.getUpdate()
|
||||
id = initializersNo() + updatesNo() and result = this.getCondition()
|
||||
or
|
||||
id = 3 and result = this.getBody()
|
||||
id = initializersNo() + updatesNo() + 1 and result = this.getBody()
|
||||
}
|
||||
|
||||
private TranslatedLocalDeclaration getDeclAndInit() {
|
||||
result = getTranslatedLocalDeclaration(stmt.getAnInitializer())
|
||||
private TranslatedElement getDeclAndInit(int index) {
|
||||
if stmt.getInitializer(index) instanceof LocalVariableDeclExpr
|
||||
then result = getTranslatedLocalDeclaration(stmt.getInitializer(index))
|
||||
else result = getTranslatedExpr(stmt.getInitializer(index))
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getAnInitializer()) }
|
||||
|
||||
TranslatedExpr getUpdate() { result = getTranslatedExpr(stmt.getAnUpdate()) }
|
||||
TranslatedExpr getUpdate(int index) { result = getTranslatedExpr(stmt.getUpdate(index)) }
|
||||
|
||||
private predicate hasUpdate() { exists(stmt.getAnUpdate()) }
|
||||
|
||||
private int initializersNo() { result = count(stmt.getAnInitializer()) }
|
||||
|
||||
private int updatesNo() { result = count(stmt.getAnUpdate()) }
|
||||
|
||||
private predicate initializerIndex(int index) { index in [0 .. initializersNo() - 1] }
|
||||
|
||||
private int updateIndex(int index) {
|
||||
result in [0 .. updatesNo() - 1] and
|
||||
index = initializersNo() + result
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if this.hasInitialization()
|
||||
then result = this.getDeclAndInit().getFirstInstruction()
|
||||
then result = this.getDeclAndInit(0).getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getDeclAndInit() and
|
||||
exists(int index |
|
||||
child = this.getDeclAndInit(index) and
|
||||
index < initializersNo() - 1 and
|
||||
result = this.getDeclAndInit(index + 1).getFirstInstruction()
|
||||
)
|
||||
or
|
||||
child = this.getDeclAndInit(initializersNo() - 1) and
|
||||
result = this.getFirstConditionInstruction()
|
||||
or
|
||||
(
|
||||
child = this.getBody() and
|
||||
if this.hasUpdate()
|
||||
then result = this.getUpdate().getFirstInstruction()
|
||||
then result = this.getUpdate(0).getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
)
|
||||
or
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction()
|
||||
exists(int index |
|
||||
child = this.getUpdate(index) and
|
||||
result = this.getUpdate(index + 1).getFirstInstruction()
|
||||
)
|
||||
or
|
||||
child = this.getUpdate(updatesNo() - 1) and
|
||||
result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,34 +733,63 @@ abstract class TranslatedSpecificJump extends TranslatedStmt {
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getTargetInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) { none() }
|
||||
|
||||
/**
|
||||
* Gets the instruction that is the target of the jump.
|
||||
*/
|
||||
abstract Instruction getTargetInstruction();
|
||||
}
|
||||
|
||||
class TranslatedBreakStmt extends TranslatedSpecificJump {
|
||||
override BreakStmt stmt;
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getEnclosingLoopOrSwitchNextInstr(stmt)
|
||||
override Instruction getTargetInstruction() {
|
||||
result = getEnclosingLoopOrSwitchNextInstr(stmt)
|
||||
}
|
||||
}
|
||||
|
||||
private Instruction getEnclosingLoopOrSwitchNextInstr(Stmt crtStmt) {
|
||||
if crtStmt instanceof LoopStmt or crtStmt instanceof SwitchStmt
|
||||
then
|
||||
result = getTranslatedStmt(crtStmt).getParent().getChildSuccessor(getTranslatedStmt(crtStmt))
|
||||
else result = this.getEnclosingLoopOrSwitchNextInstr(crtStmt.getParent())
|
||||
private Instruction getEnclosingLoopOrSwitchNextInstr(Stmt crtStmt) {
|
||||
if crtStmt instanceof LoopStmt or crtStmt instanceof SwitchStmt
|
||||
then
|
||||
result = getTranslatedStmt(crtStmt).getParent().getChildSuccessor(getTranslatedStmt(crtStmt))
|
||||
else result = getEnclosingLoopOrSwitchNextInstr(crtStmt.getParent())
|
||||
}
|
||||
|
||||
class TranslatedContinueStmt extends TranslatedSpecificJump {
|
||||
override ContinueStmt stmt;
|
||||
|
||||
override Instruction getTargetInstruction() {
|
||||
result = getEnclosingLoopTargetInstruction(stmt)
|
||||
}
|
||||
}
|
||||
|
||||
private Instruction getEnclosingLoopTargetInstruction(Stmt crtStmt) {
|
||||
if crtStmt instanceof ForStmt
|
||||
then result = getNextForInstruction(crtStmt)
|
||||
else if crtStmt instanceof LoopStmt
|
||||
then result = getTranslatedStmt(crtStmt).getFirstInstruction()
|
||||
else result = getEnclosingLoopTargetInstruction(crtStmt.getParent())
|
||||
}
|
||||
|
||||
private Instruction getNextForInstruction(ForStmt for) {
|
||||
if exists(for.getUpdate(0))
|
||||
then result = getTranslatedStmt(for).(TranslatedForStmt).getUpdate(0).getFirstInstruction()
|
||||
else if exists(for.getCondition())
|
||||
then result = getTranslatedStmt(for).(TranslatedForStmt).getCondition().getFirstInstruction()
|
||||
else result = getTranslatedStmt(for).(TranslatedForStmt).getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
class TranslatedGotoLabelStmt extends TranslatedSpecificJump {
|
||||
override GotoLabelStmt stmt;
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
override Instruction getTargetInstruction() {
|
||||
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction()
|
||||
}
|
||||
}
|
||||
@@ -743,44 +797,40 @@ class TranslatedGotoLabelStmt extends TranslatedSpecificJump {
|
||||
class TranslatedGotoCaseStmt extends TranslatedSpecificJump {
|
||||
override GotoCaseStmt stmt;
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getCase(stmt, stmt.getExpr()).getFirstInstruction()
|
||||
override Instruction getTargetInstruction() {
|
||||
result = getCase(stmt, stmt.getExpr()).getFirstInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
private TranslatedStmt getCase(Stmt crtStmt, Expr expr) {
|
||||
if crtStmt instanceof SwitchStmt
|
||||
then
|
||||
exists(CaseStmt caseStmt |
|
||||
caseStmt = crtStmt.(SwitchStmt).getACase() and
|
||||
// We check for the constant value of the expression
|
||||
// since we can't check for equality between `PatternExpr` and `Expr`
|
||||
caseStmt.getPattern().getValue() = expr.getValue() and
|
||||
result = getTranslatedStmt(caseStmt)
|
||||
)
|
||||
else result = this.getCase(crtStmt.getParent(), expr)
|
||||
}
|
||||
private TranslatedStmt getCase(Stmt crtStmt, Expr expr) {
|
||||
if crtStmt instanceof SwitchStmt
|
||||
then
|
||||
exists(CaseStmt caseStmt |
|
||||
caseStmt = crtStmt.(SwitchStmt).getACase() and
|
||||
// We check for the constant value of the expression
|
||||
// since we can't check for equality between `PatternExpr` and `Expr`
|
||||
caseStmt.getPattern().getValue() = expr.getValue() and
|
||||
result = getTranslatedStmt(caseStmt)
|
||||
)
|
||||
else result = getCase(crtStmt.getParent(), expr)
|
||||
}
|
||||
|
||||
class TranslatedGotoDefaultStmt extends TranslatedSpecificJump {
|
||||
override GotoDefaultStmt stmt;
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
override Instruction getTargetInstruction() {
|
||||
result = getDefaultCase(stmt).getFirstInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
private TranslatedStmt getDefaultCase(Stmt crtStmt) {
|
||||
if crtStmt instanceof SwitchStmt
|
||||
then
|
||||
exists(CaseStmt caseStmt |
|
||||
caseStmt = crtStmt.(SwitchStmt).getDefaultCase() and
|
||||
result = getTranslatedStmt(caseStmt)
|
||||
)
|
||||
else result = this.getDefaultCase(crtStmt.getParent())
|
||||
}
|
||||
private TranslatedStmt getDefaultCase(Stmt crtStmt) {
|
||||
if crtStmt instanceof SwitchStmt
|
||||
then
|
||||
exists(CaseStmt caseStmt |
|
||||
caseStmt = crtStmt.(SwitchStmt).getDefaultCase() and
|
||||
result = getTranslatedStmt(caseStmt)
|
||||
)
|
||||
else result = getDefaultCase(crtStmt.getParent())
|
||||
}
|
||||
|
||||
class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* (both AST generated and compiler generated).
|
||||
*/
|
||||
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.ir.implementation.Opcode
|
||||
private import semmle.code.csharp.ir.implementation.internal.OperandTag
|
||||
@@ -18,129 +17,112 @@ abstract class TranslatedCallBase extends TranslatedElement {
|
||||
override final TranslatedElement getChild(int id) {
|
||||
// We choose the child's id in the order of evaluation.
|
||||
// Note: some calls do need qualifiers, though instructions for them have already
|
||||
// been generated; eg. a constructor does not need to generate a qualifier,
|
||||
// been generated; eg. a constructor does not need to generate a qualifier,
|
||||
// though the `this` argument exists and is the result of the instruction
|
||||
// that allocated the new object. For those calls, `getQualifier()` should
|
||||
// be void.
|
||||
id = -1 and result = getQualifier() or
|
||||
id = -1 and result = getQualifier()
|
||||
or
|
||||
result = getArgument(id)
|
||||
}
|
||||
|
||||
override final Instruction getFirstInstruction() {
|
||||
if exists(getQualifier()) then
|
||||
result = getQualifier().getFirstInstruction()
|
||||
else
|
||||
result = getInstruction(CallTargetTag())
|
||||
final override Instruction getFirstInstruction() {
|
||||
if exists(getQualifier())
|
||||
then result = getQualifier().getFirstInstruction()
|
||||
else result = getInstruction(CallTargetTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getCallResultType() and
|
||||
isLValue = false
|
||||
or
|
||||
hasSideEffect() and
|
||||
tag = CallSideEffectTag() and
|
||||
(
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getCallResultType() and
|
||||
isLValue = false
|
||||
) or
|
||||
(
|
||||
hasSideEffect() and
|
||||
tag = CallSideEffectTag() and
|
||||
(
|
||||
if hasWriteSideEffect() then (
|
||||
opcode instanceof Opcode::CallSideEffect and
|
||||
resultType instanceof Language::UnknownType
|
||||
)
|
||||
else (
|
||||
opcode instanceof Opcode::CallReadSideEffect and
|
||||
resultType instanceof Language::UnknownType
|
||||
)
|
||||
) and
|
||||
isLValue = false
|
||||
) or
|
||||
(
|
||||
tag = CallTargetTag() and
|
||||
opcode instanceof Opcode::FunctionAddress and
|
||||
// Since the DB does not have a function type,
|
||||
// we just use the UnknownType
|
||||
resultType instanceof Language::UnknownType and
|
||||
isLValue = true
|
||||
)
|
||||
if hasWriteSideEffect()
|
||||
then (
|
||||
opcode instanceof Opcode::CallSideEffect and
|
||||
resultType instanceof Language::UnknownType
|
||||
) else (
|
||||
opcode instanceof Opcode::CallReadSideEffect and
|
||||
resultType instanceof Language::UnknownType
|
||||
)
|
||||
) and
|
||||
isLValue = false
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
opcode instanceof Opcode::FunctionAddress and
|
||||
// Since the DB does not have a function type,
|
||||
// we just use the UnknownType
|
||||
resultType instanceof Language::UnknownType and
|
||||
isLValue = true
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
(
|
||||
child = getQualifier() and
|
||||
result = getInstruction(CallTargetTag())
|
||||
) or
|
||||
child = getQualifier() and
|
||||
result = getInstruction(CallTargetTag())
|
||||
or
|
||||
exists(int argIndex |
|
||||
child = getArgument(argIndex) and
|
||||
if exists(getArgument(argIndex + 1)) then
|
||||
result = getArgument(argIndex + 1).getFirstInstruction()
|
||||
else
|
||||
result = getInstruction(CallTag())
|
||||
if exists(getArgument(argIndex + 1))
|
||||
then result = getArgument(argIndex + 1).getFirstInstruction()
|
||||
else result = getInstruction(CallTag())
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
EdgeKind kind) {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
(
|
||||
tag = CallTag() and
|
||||
if hasSideEffect() then
|
||||
result = getInstruction(CallSideEffectTag())
|
||||
else
|
||||
result = getParent().getChildSuccessor(this)
|
||||
) or
|
||||
(
|
||||
hasSideEffect() and
|
||||
tag = CallSideEffectTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
) or
|
||||
(
|
||||
tag = CallTargetTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getFirstArgumentOrCallInstruction()
|
||||
if hasSideEffect()
|
||||
then result = getInstruction(CallSideEffectTag())
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag,
|
||||
OperandTag operandTag) {
|
||||
(
|
||||
tag = CallTag() and
|
||||
(
|
||||
(
|
||||
operandTag instanceof CallTargetOperandTag and
|
||||
result = getInstruction(CallTargetTag())
|
||||
) or
|
||||
(
|
||||
operandTag instanceof ThisArgumentOperandTag and
|
||||
result = getQualifierResult()
|
||||
) or
|
||||
exists(PositionalArgumentOperandTag argTag |
|
||||
argTag = operandTag and
|
||||
result = getArgument(argTag.getArgIndex()).getResult()
|
||||
)
|
||||
)
|
||||
) or
|
||||
(
|
||||
tag = CallSideEffectTag() and
|
||||
or
|
||||
hasSideEffect() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
result = getUnmodeledDefinitionInstruction()
|
||||
tag = CallSideEffectTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getFirstArgumentOrCallInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
override final Type getInstructionOperandType(InstructionTag tag,
|
||||
TypedOperandTag operandTag) {
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = CallTag() and
|
||||
(
|
||||
operandTag instanceof CallTargetOperandTag and
|
||||
result = getInstruction(CallTargetTag())
|
||||
or
|
||||
operandTag instanceof ThisArgumentOperandTag and
|
||||
result = getQualifierResult()
|
||||
or
|
||||
exists(PositionalArgumentOperandTag argTag |
|
||||
argTag = operandTag and
|
||||
result = getArgument(argTag.getArgIndex()).getResult()
|
||||
)
|
||||
)
|
||||
or
|
||||
tag = CallSideEffectTag() and
|
||||
hasSideEffect() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
result = getUnmodeledDefinitionInstruction()
|
||||
}
|
||||
|
||||
final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
|
||||
tag = CallSideEffectTag() and
|
||||
hasSideEffect() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
result instanceof Language::UnknownType
|
||||
}
|
||||
|
||||
Instruction getResult() {
|
||||
result = getInstruction(CallTag())
|
||||
}
|
||||
Instruction getResult() { result = getInstruction(CallTag()) }
|
||||
|
||||
/**
|
||||
* Gets the result type of the call.
|
||||
@@ -152,16 +134,14 @@ abstract class TranslatedCallBase extends TranslatedElement {
|
||||
* function (of the element this call is attached to).
|
||||
*/
|
||||
abstract Instruction getUnmodeledDefinitionInstruction();
|
||||
|
||||
|
||||
/**
|
||||
* Holds if the call has a `this` argument.
|
||||
*/
|
||||
predicate hasQualifier() {
|
||||
exists(getQualifier())
|
||||
}
|
||||
predicate hasQualifier() { exists(getQualifier()) }
|
||||
|
||||
/**
|
||||
* Gets the expr for the qualifier of the call.
|
||||
* Gets the expr for the qualifier of the call.
|
||||
*/
|
||||
abstract TranslatedExprBase getQualifier();
|
||||
|
||||
@@ -186,10 +166,9 @@ abstract class TranslatedCallBase extends TranslatedElement {
|
||||
* argument. Otherwise, returns the call instruction.
|
||||
*/
|
||||
final Instruction getFirstArgumentOrCallInstruction() {
|
||||
if hasArguments() then
|
||||
result = getArgument(0).getFirstInstruction()
|
||||
else
|
||||
result = getInstruction(CallTag())
|
||||
if hasArguments()
|
||||
then result = getArgument(0).getFirstInstruction()
|
||||
else result = getInstruction(CallTag())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,21 +178,15 @@ abstract class TranslatedCallBase extends TranslatedElement {
|
||||
exists(getArgument(0))
|
||||
}
|
||||
|
||||
predicate hasReadSideEffect() {
|
||||
any()
|
||||
}
|
||||
predicate hasReadSideEffect() { any() }
|
||||
|
||||
predicate hasWriteSideEffect() {
|
||||
any()
|
||||
}
|
||||
predicate hasWriteSideEffect() { any() }
|
||||
|
||||
private predicate hasSideEffect() {
|
||||
hasReadSideEffect() or hasWriteSideEffect()
|
||||
}
|
||||
private predicate hasSideEffect() { hasReadSideEffect() or hasWriteSideEffect() }
|
||||
|
||||
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
|
||||
hasSideEffect() and
|
||||
tag = CallSideEffectTag() and
|
||||
result = getResult()
|
||||
hasSideEffect() and
|
||||
tag = CallSideEffectTag() and
|
||||
result = getResult()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedCondition
|
||||
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
|
||||
|
||||
|
||||
/**
|
||||
* Represents the context of the condition, ie. provides
|
||||
* information about the instruction that follows a conditional branch.
|
||||
@@ -23,30 +22,25 @@ abstract class ConditionContext extends TranslatedElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class that serves as a Base for the classes that deal with both the AST generated conditions
|
||||
* Abstract class that serves as a Base for the classes that deal with both the AST generated conditions
|
||||
* and the compiler generated ones (captures the common patterns).
|
||||
*/
|
||||
abstract class ConditionBase extends TranslatedElement {
|
||||
final ConditionContext getConditionContext() {
|
||||
result = getParent()
|
||||
}
|
||||
final ConditionContext getConditionContext() { result = getParent() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class that serves as a Base for the classes that deal with both the AST generated _value_ conditions
|
||||
* Abstract class that serves as a Base for the classes that deal with both the AST generated _value_ conditions
|
||||
* and the compiler generated ones (captures the common patterns).
|
||||
*/
|
||||
abstract class ValueConditionBase extends ConditionBase {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getValueExpr()
|
||||
}
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getValueExpr() }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getValueExpr().getFirstInstruction()
|
||||
}
|
||||
override Instruction getFirstInstruction() { result = getValueExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType instanceof VoidType and
|
||||
@@ -58,23 +52,18 @@ abstract class ValueConditionBase extends ConditionBase {
|
||||
result = getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
) or
|
||||
(
|
||||
kind instanceof FalseEdge and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
)
|
||||
kind instanceof TrueEdge and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
or
|
||||
kind instanceof FalseEdge and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag,
|
||||
OperandTag operandTag) {
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = valueExprResult()
|
||||
@@ -84,9 +73,9 @@ abstract class ValueConditionBase extends ConditionBase {
|
||||
* Gets the instruction that represents the result of the value expression.
|
||||
*/
|
||||
abstract Instruction valueExprResult();
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedElements that represents the value expression.
|
||||
*/
|
||||
abstract TranslatedElement getValueExpr();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Contains an abstract class that serves as a Base for the classes that deal with both the AST
|
||||
* Contains an abstract class that serves as a Base for the classes that deal with both the AST
|
||||
* generated declarations and the compiler generated ones (captures the common patterns).
|
||||
*/
|
||||
|
||||
@@ -13,55 +13,47 @@ private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.csharp.ir.implementation.raw.internal.TranslatedInitialization
|
||||
private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
|
||||
|
||||
|
||||
abstract class LocalVariableDeclarationBase extends TranslatedElement {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getVarAddress() }
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getVarType() and
|
||||
isLValue = true
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getVarType() and
|
||||
isLValue = false
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getVarAddress()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getVarType() and
|
||||
isLValue = true
|
||||
) or
|
||||
(
|
||||
hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getVarType() and
|
||||
isLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
if hasUninitializedInstruction() then
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
if hasUninitializedInstruction()
|
||||
then result = getInstruction(InitializerStoreTag())
|
||||
else
|
||||
if isInitializedByElement() then
|
||||
if isInitializedByElement()
|
||||
then
|
||||
// initialization is done by an element
|
||||
result = getParent().getChildSuccessor(this)
|
||||
else
|
||||
result = getInitialization().getFirstInstruction()
|
||||
) or
|
||||
else result = getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
hasUninitializedInstruction() and
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
result = getInitialization().getFirstInstruction() or
|
||||
not exists(getInitialization()) and result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
result = getInitialization().getFirstInstruction()
|
||||
or
|
||||
not exists(getInitialization()) and result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,11 +67,11 @@ abstract class LocalVariableDeclarationBase extends TranslatedElement {
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getVarAddress()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Holds if the declaration should have an `Uninitialized` instruction.
|
||||
* Compiler generated elements should override this predicate and
|
||||
* make it empty, since we always initialize the vars declared during the
|
||||
* make it empty, since we always initialize the vars declared during the
|
||||
* desugaring process.
|
||||
*/
|
||||
predicate hasUninitializedInstruction() {
|
||||
@@ -89,29 +81,27 @@ abstract class LocalVariableDeclarationBase extends TranslatedElement {
|
||||
) and
|
||||
not isInitializedByElement()
|
||||
}
|
||||
|
||||
Instruction getVarAddress() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
|
||||
Instruction getVarAddress() { result = getInstruction(InitializerVariableAddressTag()) }
|
||||
|
||||
/**
|
||||
* Gets the declared variable. For compiler generated elements, this
|
||||
* Gets the declared variable. For compiler generated elements, this
|
||||
* should be empty (since we treat temp vars differently).
|
||||
*/
|
||||
abstract LocalVariable getDeclVar();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the type of the declared variable.
|
||||
*/
|
||||
abstract Type getVarType();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the initialization, if there is one.
|
||||
* For compiler generated elements we don't treat the initialization
|
||||
* as a different step, but do it during the declaration.
|
||||
*/
|
||||
abstract TranslatedElement getInitialization();
|
||||
|
||||
|
||||
/**
|
||||
* Holds if a declaration is not explicitly initialized,
|
||||
* but will be implicitly initialized by an element.
|
||||
|
||||
@@ -11,4 +11,4 @@ abstract class TranslatedExprBase extends TranslatedElement {
|
||||
* Gets the instruction that produces the result of the expression.
|
||||
*/
|
||||
abstract Instruction getResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +285,42 @@
|
||||
| Initializers.cs:29:9:29:11 | enter Sub | Initializers.cs:29:9:29:11 | exit Sub | 11 |
|
||||
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | exit Sub | 8 |
|
||||
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | exit Sub | 18 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:9:13:9:28 | ... == ... | 7 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | exit M1 | 1 |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:10:13:10:19 | return ...; | 1 |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | 5 |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | 2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | 11 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:15:10:15:11 | exit M2 | 1 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | 5 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:24:29:24:32 | access to parameter args | 3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:22:10:22:11 | exit M3 | 1 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | 1 |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | 3 |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | 5 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:32:26:32:27 | access to local variable xs | 7 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:29:10:29:11 | exit M4 | 1 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | 1 |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | 4 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | 18 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:36:10:36:11 | exit M5 | 1 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | 1 |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | 3 |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | 7 |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:49:9:52:9 | {...} | 13 |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:51:13:51:23 | goto ...; | 5 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:60:17:60:17 | access to parameter b | 15 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:55:10:55:11 | exit M7 | 1 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | 4 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | 4 |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | 9 |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | 3 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:69:14:69:23 | call to method Any | 6 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:67:10:67:11 | exit M8 | 1 |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:70:13:70:19 | return ...; | 1 |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:72:28:72:31 | access to parameter args | 4 |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | 1 |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | 4 |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:23:3:23 | access to parameter i | 3 |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:9:3:10 | exit M1 | 1 |
|
||||
| NullCoalescing.cs:3:28:3:28 | 0 | NullCoalescing.cs:3:28:3:28 | 0 | 1 |
|
||||
|
||||
@@ -227,6 +227,40 @@ conditionBlock
|
||||
| Foreach.cs:32:9:33:11 | foreach (... ... in ...) ... | Foreach.cs:32:23:32:23 | String x | false |
|
||||
| Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | Foreach.cs:36:10:36:11 | exit M6 | true |
|
||||
| Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | Foreach.cs:38:26:38:26 | String x | false |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:10:13:10:19 | return ...; | true |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:11:21:11:23 | String arg | false |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:11:28:11:31 | access to parameter args | false |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:21:11:23 | String arg | false |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:15:10:15:11 | exit M2 | false |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:18:21:18:21 | String x | false |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:15:10:15:11 | exit M2 | true |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | exit M3 | true |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:22:24:24 | Char arg | false |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 | false |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:25:26:25:29 | Char arg0 | false |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | exit M4 | true |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:21:32:21 | String x | false |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:36:10:36:11 | exit M5 | false |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | false |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:40:21:40:21 | String x | false |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:41:25:41:25 | String y | false |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | exit M5 | true |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:36:10:36:11 | exit M5 | false |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | false |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:41:25:41:25 | String y | false |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:36:10:36:11 | exit M5 | true |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | true |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | false |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | true |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | true |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | false |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | false |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | false |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:70:13:70:19 | return ...; | false |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:71:9:71:21 | ...; | true |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | true |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:72:21:72:23 | String arg | true |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:21:72:23 | String arg | false |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:28:3:28 | 0 | true |
|
||||
| NullCoalescing.cs:5:9:5:10 | enter M2 | NullCoalescing.cs:5:30:5:34 | false | true |
|
||||
| NullCoalescing.cs:5:9:5:10 | enter M2 | NullCoalescing.cs:5:39:5:39 | 0 | true |
|
||||
@@ -822,6 +856,16 @@ conditionFlow
|
||||
| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:69:111:75 | "input" | false |
|
||||
| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:34:116:34 | 0 | true |
|
||||
| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:38:116:38 | 1 | false |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:10:13:10:19 | return ...; | true |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:11:28:11:31 | access to parameter args | false |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | false |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | true |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | true |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | false |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | false |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | true |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:70:13:70:19 | return ...; | false |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:71:9:71:21 | ...; | true |
|
||||
| NullCoalescing.cs:5:25:5:25 | access to parameter b | NullCoalescing.cs:5:39:5:39 | 0 | true |
|
||||
| NullCoalescing.cs:5:25:5:25 | access to parameter b | NullCoalescing.cs:5:43:5:43 | 1 | false |
|
||||
| NullCoalescing.cs:5:30:5:34 | false | NullCoalescing.cs:5:43:5:43 | 1 | false |
|
||||
|
||||
@@ -1310,6 +1310,155 @@ dominance
|
||||
| Initializers.cs:33:33:33:33 | access to parameter i | Initializers.cs:33:37:33:37 | access to parameter j |
|
||||
| Initializers.cs:33:33:33:37 | ... + ... | Initializers.cs:33:29:33:37 | ... = ... |
|
||||
| Initializers.cs:33:37:33:37 | access to parameter j | Initializers.cs:33:33:33:37 | ... + ... |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:8:5:13:5 | {...} |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:9:9:10:19 | if (...) ... |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:9:13:9:16 | access to parameter args |
|
||||
| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:9:13:9:23 | access to property Length |
|
||||
| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:9:28:9:28 | 0 |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:9:13:9:28 | ... == ... |
|
||||
| LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:12:13:12:35 | ...; |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:12:31:12:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:12:13:12:34 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:16:5:20:5 | {...} |
|
||||
| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:17:9:17:47 | ... ...; |
|
||||
| LoopUnrolling.cs:17:9:17:47 | ... ...; | LoopUnrolling.cs:17:18:17:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | LoopUnrolling.cs:18:26:18:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | LoopUnrolling.cs:17:32:17:34 | "a" |
|
||||
| LoopUnrolling.cs:17:30:17:46 | { ..., ... } | LoopUnrolling.cs:17:13:17:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:17:32:17:34 | "a" | LoopUnrolling.cs:17:37:17:39 | "b" |
|
||||
| LoopUnrolling.cs:17:37:17:39 | "b" | LoopUnrolling.cs:17:42:17:44 | "c" |
|
||||
| LoopUnrolling.cs:17:42:17:44 | "c" | LoopUnrolling.cs:17:30:17:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:15:10:15:11 | exit M2 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:19:13:19:33 | ...; |
|
||||
| LoopUnrolling.cs:18:26:18:27 | access to local variable xs | LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:19:31:19:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:19:13:19:32 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:23:5:27:5 | {...} |
|
||||
| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:24:29:24:32 | access to parameter args |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | exit M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:25:34:25:37 | access to parameter args |
|
||||
| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:26:17:26:40 | ...; |
|
||||
| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 |
|
||||
| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:26:17:26:39 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:30:5:34:5 | {...} |
|
||||
| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:31:9:31:31 | ... ...; |
|
||||
| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:31:29:31:29 | 0 |
|
||||
| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:32:26:32:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:31:13:31:30 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:31:18:31:30 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | exit M4 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:33:13:33:33 | ...; |
|
||||
| LoopUnrolling.cs:32:26:32:27 | access to local variable xs | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:33:13:33:33 | ...; | LoopUnrolling.cs:33:31:33:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:33:31:33:31 | access to local variable x | LoopUnrolling.cs:33:13:33:32 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:37:5:43:5 | {...} |
|
||||
| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:38:9:38:47 | ... ...; |
|
||||
| LoopUnrolling.cs:38:9:38:47 | ... ...; | LoopUnrolling.cs:38:18:38:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | LoopUnrolling.cs:39:9:39:47 | ... ...; |
|
||||
| LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | LoopUnrolling.cs:38:32:38:34 | "a" |
|
||||
| LoopUnrolling.cs:38:30:38:46 | { ..., ... } | LoopUnrolling.cs:38:13:38:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:38:32:38:34 | "a" | LoopUnrolling.cs:38:37:38:39 | "b" |
|
||||
| LoopUnrolling.cs:38:37:38:39 | "b" | LoopUnrolling.cs:38:42:38:44 | "c" |
|
||||
| LoopUnrolling.cs:38:42:38:44 | "c" | LoopUnrolling.cs:38:30:38:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:39:9:39:47 | ... ...; | LoopUnrolling.cs:39:18:39:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | LoopUnrolling.cs:40:26:40:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | LoopUnrolling.cs:39:32:39:34 | "0" |
|
||||
| LoopUnrolling.cs:39:30:39:46 | { ..., ... } | LoopUnrolling.cs:39:13:39:46 | String[] ys = ... |
|
||||
| LoopUnrolling.cs:39:32:39:34 | "0" | LoopUnrolling.cs:39:37:39:39 | "1" |
|
||||
| LoopUnrolling.cs:39:37:39:39 | "1" | LoopUnrolling.cs:39:42:39:44 | "2" |
|
||||
| LoopUnrolling.cs:39:42:39:44 | "2" | LoopUnrolling.cs:39:30:39:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:41:30:41:31 | access to local variable ys |
|
||||
| LoopUnrolling.cs:40:26:40:27 | access to local variable xs | LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:42:17:42:41 | ...; |
|
||||
| LoopUnrolling.cs:41:30:41:31 | access to local variable ys | LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:42:35:42:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:42:39:42:39 | access to local variable y |
|
||||
| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:42:17:42:40 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:42:35:42:39 | ... + ... |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:46:5:53:5 | {...} |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:47:9:47:47 | ... ...; |
|
||||
| LoopUnrolling.cs:47:9:47:47 | ... ...; | LoopUnrolling.cs:47:18:47:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | LoopUnrolling.cs:48:26:48:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | LoopUnrolling.cs:47:32:47:34 | "a" |
|
||||
| LoopUnrolling.cs:47:30:47:46 | { ..., ... } | LoopUnrolling.cs:47:13:47:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:47:32:47:34 | "a" | LoopUnrolling.cs:47:37:47:39 | "b" |
|
||||
| LoopUnrolling.cs:47:37:47:39 | "b" | LoopUnrolling.cs:47:42:47:44 | "c" |
|
||||
| LoopUnrolling.cs:47:42:47:44 | "c" | LoopUnrolling.cs:47:30:47:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | LoopUnrolling.cs:48:21:48:21 | String x |
|
||||
| LoopUnrolling.cs:48:21:48:21 | String x | LoopUnrolling.cs:49:9:52:9 | {...} |
|
||||
| LoopUnrolling.cs:48:26:48:27 | access to local variable xs | LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:50:13:50:17 | Label: |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:50:20:50:40 | ...; |
|
||||
| LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | LoopUnrolling.cs:51:13:51:23 | goto ...; |
|
||||
| LoopUnrolling.cs:50:20:50:40 | ...; | LoopUnrolling.cs:50:38:50:38 | access to local variable x |
|
||||
| LoopUnrolling.cs:50:38:50:38 | access to local variable x | LoopUnrolling.cs:50:20:50:39 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:56:5:65:5 | {...} |
|
||||
| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:57:9:57:47 | ... ...; |
|
||||
| LoopUnrolling.cs:57:9:57:47 | ... ...; | LoopUnrolling.cs:57:18:57:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | LoopUnrolling.cs:58:26:58:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | LoopUnrolling.cs:57:32:57:34 | "a" |
|
||||
| LoopUnrolling.cs:57:30:57:46 | { ..., ... } | LoopUnrolling.cs:57:13:57:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:57:32:57:34 | "a" | LoopUnrolling.cs:57:37:57:39 | "b" |
|
||||
| LoopUnrolling.cs:57:37:57:39 | "b" | LoopUnrolling.cs:57:42:57:44 | "c" |
|
||||
| LoopUnrolling.cs:57:42:57:44 | "c" | LoopUnrolling.cs:57:30:57:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | LoopUnrolling.cs:58:21:58:21 | String x |
|
||||
| LoopUnrolling.cs:58:21:58:21 | String x | LoopUnrolling.cs:59:9:64:9 | {...} |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} |
|
||||
| LoopUnrolling.cs:58:26:58:27 | access to local variable xs | LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:60:13:61:37 | if (...) ... |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:60:17:60:17 | access to parameter b |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x |
|
||||
| LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x |
|
||||
| LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:68:5:74:5 | {...} |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:69:9:70:19 | if (...) ... |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:69:13:69:23 | !... |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:69:14:69:17 | access to parameter args |
|
||||
| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:69:14:69:23 | call to method Any |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:71:9:71:20 | call to method Clear |
|
||||
| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:72:28:72:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:12 | access to parameter args |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:73:13:73:35 | ...; |
|
||||
| LoopUnrolling.cs:72:28:72:31 | access to parameter args | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:73:13:73:35 | ...; | LoopUnrolling.cs:73:31:73:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:73:31:73:33 | access to local variable arg | LoopUnrolling.cs:73:13:73:34 | call to method WriteLine |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:23:3:28 | ... ?? ... |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:9:3:10 | exit M1 |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:28:3:28 | 0 |
|
||||
@@ -3946,6 +4095,154 @@ postDominance
|
||||
| Initializers.cs:33:33:33:33 | access to parameter i | Initializers.cs:33:29:33:29 | this access |
|
||||
| Initializers.cs:33:33:33:37 | ... + ... | Initializers.cs:33:37:33:37 | access to parameter j |
|
||||
| Initializers.cs:33:37:33:37 | access to parameter j | Initializers.cs:33:33:33:33 | access to parameter i |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:7:10:7:11 | enter M1 |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:8:5:13:5 | {...} |
|
||||
| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:9:9:10:19 | if (...) ... |
|
||||
| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:9:13:9:16 | access to parameter args |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:9:28:9:28 | 0 |
|
||||
| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:9:13:9:23 | access to property Length |
|
||||
| LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:12:13:12:34 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:12:31:12:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:12:13:12:35 | ...; |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:15:10:15:11 | enter M2 |
|
||||
| LoopUnrolling.cs:17:9:17:47 | ... ...; | LoopUnrolling.cs:16:5:20:5 | {...} |
|
||||
| LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | LoopUnrolling.cs:17:30:17:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | LoopUnrolling.cs:17:9:17:47 | ... ...; |
|
||||
| LoopUnrolling.cs:17:30:17:46 | { ..., ... } | LoopUnrolling.cs:17:42:17:44 | "c" |
|
||||
| LoopUnrolling.cs:17:32:17:34 | "a" | LoopUnrolling.cs:17:18:17:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:17:37:17:39 | "b" | LoopUnrolling.cs:17:32:17:34 | "a" |
|
||||
| LoopUnrolling.cs:17:42:17:44 | "c" | LoopUnrolling.cs:17:37:17:39 | "b" |
|
||||
| LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | LoopUnrolling.cs:18:26:18:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:19:13:19:32 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:18:26:18:27 | access to local variable xs | LoopUnrolling.cs:17:13:17:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:19:31:19:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:19:13:19:33 | ...; |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:22:10:22:11 | enter M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:29:24:32 | access to parameter args |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:23:5:27:5 | {...} |
|
||||
| LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | LoopUnrolling.cs:25:34:25:37 | access to parameter args |
|
||||
| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:26:17:26:39 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 |
|
||||
| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:26:17:26:40 | ...; |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:29:10:29:11 | enter M4 |
|
||||
| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:30:5:34:5 | {...} |
|
||||
| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:31:18:31:30 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:31:29:31:29 | 0 |
|
||||
| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:31:9:31:31 | ... ...; |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:26:32:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:33:13:33:32 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:32:26:32:27 | access to local variable xs | LoopUnrolling.cs:31:13:31:30 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | LoopUnrolling.cs:33:31:33:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:33:13:33:33 | ...; | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:33:31:33:31 | access to local variable x | LoopUnrolling.cs:33:13:33:33 | ...; |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:38:9:38:47 | ... ...; | LoopUnrolling.cs:37:5:43:5 | {...} |
|
||||
| LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | LoopUnrolling.cs:38:30:38:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | LoopUnrolling.cs:38:9:38:47 | ... ...; |
|
||||
| LoopUnrolling.cs:38:30:38:46 | { ..., ... } | LoopUnrolling.cs:38:42:38:44 | "c" |
|
||||
| LoopUnrolling.cs:38:32:38:34 | "a" | LoopUnrolling.cs:38:18:38:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:38:37:38:39 | "b" | LoopUnrolling.cs:38:32:38:34 | "a" |
|
||||
| LoopUnrolling.cs:38:42:38:44 | "c" | LoopUnrolling.cs:38:37:38:39 | "b" |
|
||||
| LoopUnrolling.cs:39:9:39:47 | ... ...; | LoopUnrolling.cs:38:13:38:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | LoopUnrolling.cs:39:30:39:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | LoopUnrolling.cs:39:9:39:47 | ... ...; |
|
||||
| LoopUnrolling.cs:39:30:39:46 | { ..., ... } | LoopUnrolling.cs:39:42:39:44 | "2" |
|
||||
| LoopUnrolling.cs:39:32:39:34 | "0" | LoopUnrolling.cs:39:18:39:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:39:37:39:39 | "1" | LoopUnrolling.cs:39:32:39:34 | "0" |
|
||||
| LoopUnrolling.cs:39:42:39:44 | "2" | LoopUnrolling.cs:39:37:39:39 | "1" |
|
||||
| LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | LoopUnrolling.cs:40:26:40:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:40:26:40:27 | access to local variable xs | LoopUnrolling.cs:39:13:39:46 | String[] ys = ... |
|
||||
| LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | LoopUnrolling.cs:41:30:41:31 | access to local variable ys |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:42:17:42:40 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:41:30:41:31 | access to local variable ys | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:42:35:42:39 | ... + ... |
|
||||
| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:42:17:42:41 | ...; |
|
||||
| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:42:39:42:39 | access to local variable y |
|
||||
| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:42:35:42:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:45:10:45:11 | enter M6 |
|
||||
| LoopUnrolling.cs:47:9:47:47 | ... ...; | LoopUnrolling.cs:46:5:53:5 | {...} |
|
||||
| LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | LoopUnrolling.cs:47:30:47:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | LoopUnrolling.cs:47:9:47:47 | ... ...; |
|
||||
| LoopUnrolling.cs:47:30:47:46 | { ..., ... } | LoopUnrolling.cs:47:42:47:44 | "c" |
|
||||
| LoopUnrolling.cs:47:32:47:34 | "a" | LoopUnrolling.cs:47:18:47:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:47:37:47:39 | "b" | LoopUnrolling.cs:47:32:47:34 | "a" |
|
||||
| LoopUnrolling.cs:47:42:47:44 | "c" | LoopUnrolling.cs:47:37:47:39 | "b" |
|
||||
| LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | LoopUnrolling.cs:48:26:48:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:48:21:48:21 | String x | LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:48:26:48:27 | access to local variable xs | LoopUnrolling.cs:47:13:47:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:48:21:48:21 | String x |
|
||||
| LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | LoopUnrolling.cs:50:38:50:38 | access to local variable x |
|
||||
| LoopUnrolling.cs:50:20:50:40 | ...; | LoopUnrolling.cs:50:13:50:17 | Label: |
|
||||
| LoopUnrolling.cs:50:38:50:38 | access to local variable x | LoopUnrolling.cs:50:20:50:40 | ...; |
|
||||
| LoopUnrolling.cs:51:13:51:23 | goto ...; | LoopUnrolling.cs:50:20:50:39 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:55:10:55:11 | enter M7 |
|
||||
| LoopUnrolling.cs:57:9:57:47 | ... ...; | LoopUnrolling.cs:56:5:65:5 | {...} |
|
||||
| LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | LoopUnrolling.cs:57:30:57:46 | { ..., ... } |
|
||||
| LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | LoopUnrolling.cs:57:9:57:47 | ... ...; |
|
||||
| LoopUnrolling.cs:57:30:57:46 | { ..., ... } | LoopUnrolling.cs:57:42:57:44 | "c" |
|
||||
| LoopUnrolling.cs:57:32:57:34 | "a" | LoopUnrolling.cs:57:18:57:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:57:37:57:39 | "b" | LoopUnrolling.cs:57:32:57:34 | "a" |
|
||||
| LoopUnrolling.cs:57:42:57:44 | "c" | LoopUnrolling.cs:57:37:57:39 | "b" |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | LoopUnrolling.cs:58:26:58:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:58:21:58:21 | String x | LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:58:26:58:27 | access to local variable xs | LoopUnrolling.cs:57:13:57:46 | String[] xs = ... |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:58:21:58:21 | String x |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:59:9:64:9 | {...} |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:60:13:61:37 | if (...) ... |
|
||||
| LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b |
|
||||
| LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... |
|
||||
| LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x |
|
||||
| LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b |
|
||||
| LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:67:10:67:11 | enter M8 |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:68:5:74:5 | {...} |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:69:9:70:19 | if (...) ... |
|
||||
| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:69:13:69:23 | !... |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:69:14:69:17 | access to parameter args |
|
||||
| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:71:9:71:12 | access to parameter args |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:28:72:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:73:13:73:34 | call to method WriteLine |
|
||||
| LoopUnrolling.cs:72:28:72:31 | access to parameter args | LoopUnrolling.cs:71:9:71:20 | call to method Clear |
|
||||
| LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | LoopUnrolling.cs:73:31:73:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:73:13:73:35 | ...; | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:73:31:73:33 | access to local variable arg | LoopUnrolling.cs:73:13:73:35 | ...; |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:23:3:23 | access to parameter i |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:28:3:28 | 0 |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:23:3:28 | ... ?? ... |
|
||||
@@ -5934,6 +6231,89 @@ blockDominance
|
||||
| Initializers.cs:29:9:29:11 | enter Sub | Initializers.cs:29:9:29:11 | enter Sub |
|
||||
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | enter Sub |
|
||||
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | enter Sub |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:7:10:7:11 | enter M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:7:10:7:11 | exit M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | exit M1 |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:15:10:15:11 | enter M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:15:10:15:11 | exit M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:15:10:15:11 | exit M2 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:15:10:15:11 | exit M2 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:22:10:22:11 | enter M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:22:10:22:11 | exit M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:22:10:22:11 | exit M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | exit M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:29:10:29:11 | enter M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:29:10:29:11 | exit M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:29:10:29:11 | exit M4 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | exit M4 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:45:10:45:11 | enter M6 |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:50:13:50:17 | Label: |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:50:13:50:17 | Label: |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:55:10:55:11 | enter M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:55:10:55:11 | exit M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:55:10:55:11 | exit M7 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:67:10:67:11 | enter M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:67:10:67:11 | exit M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:67:10:67:11 | exit M8 |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:9:3:10 | enter M1 |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:9:3:10 | exit M1 |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:28:3:28 | 0 |
|
||||
@@ -8030,6 +8410,87 @@ postBlockDominance
|
||||
| Initializers.cs:29:9:29:11 | enter Sub | Initializers.cs:29:9:29:11 | enter Sub |
|
||||
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | enter Sub |
|
||||
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | enter Sub |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:7:10:7:11 | enter M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | enter M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | exit M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:15:10:15:11 | enter M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:15:10:15:11 | enter M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:15:10:15:11 | exit M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:15:10:15:11 | enter M2 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:22:10:22:11 | enter M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:22:10:22:11 | enter M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:22:10:22:11 | exit M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | enter M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:29:10:29:11 | enter M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:29:10:29:11 | enter M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:29:10:29:11 | exit M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | enter M4 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:36:10:36:11 | exit M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:36:10:36:11 | enter M5 |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:45:10:45:11 | enter M6 |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:50:13:50:17 | Label: |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:55:10:55:11 | enter M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:55:10:55:11 | enter M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:55:10:55:11 | exit M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:67:10:67:11 | enter M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:67:10:67:11 | enter M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:67:10:67:11 | exit M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:9:3:10 | enter M1 |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:9:3:10 | enter M1 |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:9:3:10 | exit M1 |
|
||||
|
||||
@@ -1428,6 +1428,166 @@ nodeEnclosing
|
||||
| Initializers.cs:33:33:33:33 | access to parameter i | Initializers.cs:33:9:33:11 | Sub |
|
||||
| Initializers.cs:33:33:33:37 | ... + ... | Initializers.cs:33:9:33:11 | Sub |
|
||||
| Initializers.cs:33:37:33:37 | access to parameter j | Initializers.cs:33:9:33:11 | Sub |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:9:17:47 | ... ...; | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:30:17:46 | { ..., ... } | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:32:17:34 | "a" | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:37:17:39 | "b" | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:17:42:17:44 | "c" | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:18:26:18:27 | access to local variable xs | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:32:26:32:27 | access to local variable xs | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:33:13:33:33 | ...; | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:33:31:33:31 | access to local variable x | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:9:38:47 | ... ...; | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:30:38:46 | { ..., ... } | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:32:38:34 | "a" | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:37:38:39 | "b" | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:38:42:38:44 | "c" | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:9:39:47 | ... ...; | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:30:39:46 | { ..., ... } | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:32:39:34 | "0" | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:37:39:39 | "1" | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:39:42:39:44 | "2" | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:40:26:40:27 | access to local variable xs | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:41:30:41:31 | access to local variable ys | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:9:47:47 | ... ...; | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:30:47:46 | { ..., ... } | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:32:47:34 | "a" | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:37:47:39 | "b" | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:47:42:47:44 | "c" | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:48:21:48:21 | String x | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:48:26:48:27 | access to local variable xs | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:50:20:50:40 | ...; | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:50:38:50:38 | access to local variable x | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:51:13:51:23 | goto ...; | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:9:57:47 | ... ...; | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:30:57:46 | { ..., ... } | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:32:57:34 | "a" | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:37:57:39 | "b" | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:57:42:57:44 | "c" | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | String x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:26:58:27 | access to local variable xs | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:72:28:72:31 | access to parameter args | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:73:13:73:35 | ...; | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:73:31:73:33 | access to local variable arg | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:9:3:10 | M1 |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:9:3:10 | M1 |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:9:3:10 | M1 |
|
||||
@@ -3150,6 +3310,42 @@ blockEnclosing
|
||||
| Initializers.cs:29:9:29:11 | enter Sub | Initializers.cs:29:9:29:11 | Sub |
|
||||
| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | Sub |
|
||||
| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | Sub |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:7:10:7:11 | exit M1 | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:7:10:7:11 | M1 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:15:10:15:11 | exit M2 | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:15:10:15:11 | M2 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:22:10:22:11 | exit M3 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:22:10:22:11 | M3 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:29:10:29:11 | exit M4 | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:29:10:29:11 | M4 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:36:10:36:11 | exit M5 | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:36:10:36:11 | M5 |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:45:10:45:11 | M6 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:55:10:55:11 | exit M7 | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:55:10:55:11 | M7 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:67:10:67:11 | exit M8 | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:67:10:67:11 | M8 |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:9:3:10 | M1 |
|
||||
| NullCoalescing.cs:3:9:3:10 | exit M1 | NullCoalescing.cs:3:9:3:10 | M1 |
|
||||
| NullCoalescing.cs:3:28:3:28 | 0 | NullCoalescing.cs:3:9:3:10 | M1 |
|
||||
|
||||
@@ -1075,6 +1075,139 @@
|
||||
| Initializers.cs:33:33:33:33 | access to parameter i | Initializers.cs:33:33:33:33 | access to parameter i |
|
||||
| Initializers.cs:33:33:33:37 | ... + ... | Initializers.cs:33:33:33:33 | access to parameter i |
|
||||
| Initializers.cs:33:37:33:37 | access to parameter j | Initializers.cs:33:37:33:37 | access to parameter j |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:8:5:13:5 | {...} |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:9:9:10:19 | if (...) ... |
|
||||
| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:9:13:9:16 | access to parameter args |
|
||||
| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:9:13:9:16 | access to parameter args |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:9:13:9:16 | access to parameter args |
|
||||
| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:9:28:9:28 | 0 |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:10:13:10:19 | return ...; |
|
||||
| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:21:11:23 | String arg |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:28:11:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:12:31:12:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:12:13:12:35 | ...; |
|
||||
| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:12:31:12:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:16:5:20:5 | {...} |
|
||||
| LoopUnrolling.cs:17:9:17:47 | ... ...; | LoopUnrolling.cs:17:9:17:47 | ... ...; |
|
||||
| LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | LoopUnrolling.cs:17:18:17:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:17:18:17:46 | 3 | LoopUnrolling.cs:17:18:17:46 | 3 |
|
||||
| LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | LoopUnrolling.cs:17:18:17:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:17:30:17:46 | { ..., ... } | LoopUnrolling.cs:17:32:17:34 | "a" |
|
||||
| LoopUnrolling.cs:17:32:17:34 | "a" | LoopUnrolling.cs:17:32:17:34 | "a" |
|
||||
| LoopUnrolling.cs:17:37:17:39 | "b" | LoopUnrolling.cs:17:37:17:39 | "b" |
|
||||
| LoopUnrolling.cs:17:42:17:44 | "c" | LoopUnrolling.cs:17:42:17:44 | "c" |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:18:26:18:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:18:21:18:21 | String x |
|
||||
| LoopUnrolling.cs:18:26:18:27 | access to local variable xs | LoopUnrolling.cs:18:26:18:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:19:31:19:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:19:13:19:33 | ...; |
|
||||
| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:19:31:19:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:23:5:27:5 | {...} |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:29:24:32 | access to parameter args |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:24:22:24:24 | Char arg |
|
||||
| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:24:29:24:32 | access to parameter args |
|
||||
| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:34:25:37 | access to parameter args |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:25:26:25:29 | Char arg0 |
|
||||
| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:25:34:25:37 | access to parameter args |
|
||||
| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 |
|
||||
| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:26:17:26:40 | ...; |
|
||||
| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 |
|
||||
| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:30:5:34:5 | {...} |
|
||||
| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:31:9:31:31 | ... ...; |
|
||||
| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:31:29:31:29 | 0 |
|
||||
| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:31:29:31:29 | 0 |
|
||||
| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:31:29:31:29 | 0 |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:26:32:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:32:21:32:21 | String x |
|
||||
| LoopUnrolling.cs:32:26:32:27 | access to local variable xs | LoopUnrolling.cs:32:26:32:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | LoopUnrolling.cs:33:31:33:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:33:13:33:33 | ...; | LoopUnrolling.cs:33:13:33:33 | ...; |
|
||||
| LoopUnrolling.cs:33:31:33:31 | access to local variable x | LoopUnrolling.cs:33:31:33:31 | access to local variable x |
|
||||
| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:37:5:43:5 | {...} |
|
||||
| LoopUnrolling.cs:38:9:38:47 | ... ...; | LoopUnrolling.cs:38:9:38:47 | ... ...; |
|
||||
| LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | LoopUnrolling.cs:38:18:38:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:38:18:38:46 | 3 | LoopUnrolling.cs:38:18:38:46 | 3 |
|
||||
| LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | LoopUnrolling.cs:38:18:38:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:38:30:38:46 | { ..., ... } | LoopUnrolling.cs:38:32:38:34 | "a" |
|
||||
| LoopUnrolling.cs:38:32:38:34 | "a" | LoopUnrolling.cs:38:32:38:34 | "a" |
|
||||
| LoopUnrolling.cs:38:37:38:39 | "b" | LoopUnrolling.cs:38:37:38:39 | "b" |
|
||||
| LoopUnrolling.cs:38:42:38:44 | "c" | LoopUnrolling.cs:38:42:38:44 | "c" |
|
||||
| LoopUnrolling.cs:39:9:39:47 | ... ...; | LoopUnrolling.cs:39:9:39:47 | ... ...; |
|
||||
| LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | LoopUnrolling.cs:39:18:39:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:39:18:39:46 | 3 | LoopUnrolling.cs:39:18:39:46 | 3 |
|
||||
| LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | LoopUnrolling.cs:39:18:39:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:39:30:39:46 | { ..., ... } | LoopUnrolling.cs:39:32:39:34 | "0" |
|
||||
| LoopUnrolling.cs:39:32:39:34 | "0" | LoopUnrolling.cs:39:32:39:34 | "0" |
|
||||
| LoopUnrolling.cs:39:37:39:39 | "1" | LoopUnrolling.cs:39:37:39:39 | "1" |
|
||||
| LoopUnrolling.cs:39:42:39:44 | "2" | LoopUnrolling.cs:39:42:39:44 | "2" |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:26:40:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:21:40:21 | String x |
|
||||
| LoopUnrolling.cs:40:26:40:27 | access to local variable xs | LoopUnrolling.cs:40:26:40:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:41:30:41:31 | access to local variable ys |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:41:25:41:25 | String y |
|
||||
| LoopUnrolling.cs:41:30:41:31 | access to local variable ys | LoopUnrolling.cs:41:30:41:31 | access to local variable ys |
|
||||
| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:42:35:42:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:42:17:42:41 | ...; |
|
||||
| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:42:35:42:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:42:35:42:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:42:39:42:39 | access to local variable y |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:46:5:53:5 | {...} |
|
||||
| LoopUnrolling.cs:47:9:47:47 | ... ...; | LoopUnrolling.cs:47:9:47:47 | ... ...; |
|
||||
| LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | LoopUnrolling.cs:47:18:47:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:47:18:47:46 | 3 | LoopUnrolling.cs:47:18:47:46 | 3 |
|
||||
| LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | LoopUnrolling.cs:47:18:47:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:47:30:47:46 | { ..., ... } | LoopUnrolling.cs:47:32:47:34 | "a" |
|
||||
| LoopUnrolling.cs:47:32:47:34 | "a" | LoopUnrolling.cs:47:32:47:34 | "a" |
|
||||
| LoopUnrolling.cs:47:37:47:39 | "b" | LoopUnrolling.cs:47:37:47:39 | "b" |
|
||||
| LoopUnrolling.cs:47:42:47:44 | "c" | LoopUnrolling.cs:47:42:47:44 | "c" |
|
||||
| LoopUnrolling.cs:48:9:52:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:48:26:48:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:48:21:48:21 | String x | LoopUnrolling.cs:48:21:48:21 | String x |
|
||||
| LoopUnrolling.cs:48:26:48:27 | access to local variable xs | LoopUnrolling.cs:48:26:48:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:49:9:52:9 | {...} |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:50:13:50:17 | Label: |
|
||||
| LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | LoopUnrolling.cs:50:38:50:38 | access to local variable x |
|
||||
| LoopUnrolling.cs:50:20:50:40 | ...; | LoopUnrolling.cs:50:20:50:40 | ...; |
|
||||
| LoopUnrolling.cs:50:38:50:38 | access to local variable x | LoopUnrolling.cs:50:38:50:38 | access to local variable x |
|
||||
| LoopUnrolling.cs:51:13:51:23 | goto ...; | LoopUnrolling.cs:51:13:51:23 | goto ...; |
|
||||
| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:56:5:65:5 | {...} |
|
||||
| LoopUnrolling.cs:57:9:57:47 | ... ...; | LoopUnrolling.cs:57:9:57:47 | ... ...; |
|
||||
| LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | LoopUnrolling.cs:57:18:57:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:57:18:57:46 | 3 | LoopUnrolling.cs:57:18:57:46 | 3 |
|
||||
| LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | LoopUnrolling.cs:57:18:57:46 | array creation of type String[] |
|
||||
| LoopUnrolling.cs:57:30:57:46 | { ..., ... } | LoopUnrolling.cs:57:32:57:34 | "a" |
|
||||
| LoopUnrolling.cs:57:32:57:34 | "a" | LoopUnrolling.cs:57:32:57:34 | "a" |
|
||||
| LoopUnrolling.cs:57:37:57:39 | "b" | LoopUnrolling.cs:57:37:57:39 | "b" |
|
||||
| LoopUnrolling.cs:57:42:57:44 | "c" | LoopUnrolling.cs:57:42:57:44 | "c" |
|
||||
| LoopUnrolling.cs:58:9:64:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:58:26:58:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:58:21:58:21 | String x | LoopUnrolling.cs:58:21:58:21 | String x |
|
||||
| LoopUnrolling.cs:58:26:58:27 | access to local variable xs | LoopUnrolling.cs:58:26:58:27 | access to local variable xs |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:59:9:64:9 | {...} |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:60:13:61:37 | if (...) ... |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:60:17:60:17 | access to parameter b |
|
||||
| LoopUnrolling.cs:61:17:61:36 | call to method WriteLine | LoopUnrolling.cs:61:35:61:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:61:17:61:37 | ...; | LoopUnrolling.cs:61:17:61:37 | ...; |
|
||||
| LoopUnrolling.cs:61:35:61:35 | access to local variable x | LoopUnrolling.cs:61:35:61:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:62:13:63:37 | if (...) ... | LoopUnrolling.cs:62:13:63:37 | if (...) ... |
|
||||
| LoopUnrolling.cs:62:17:62:17 | access to parameter b | LoopUnrolling.cs:62:17:62:17 | access to parameter b |
|
||||
| LoopUnrolling.cs:63:17:63:36 | call to method WriteLine | LoopUnrolling.cs:63:35:63:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:63:17:63:37 | ...; | LoopUnrolling.cs:63:17:63:37 | ...; |
|
||||
| LoopUnrolling.cs:63:35:63:35 | access to local variable x | LoopUnrolling.cs:63:35:63:35 | access to local variable x |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:68:5:74:5 | {...} |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:69:9:70:19 | if (...) ... |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:69:13:69:23 | !... |
|
||||
| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:69:14:69:17 | access to parameter args |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:69:14:69:17 | access to parameter args |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:70:13:70:19 | return ...; |
|
||||
| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:71:9:71:12 | access to parameter args |
|
||||
| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:71:9:71:12 | access to parameter args |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:21 | ...; |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:28:72:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:72:21:72:23 | String arg |
|
||||
| LoopUnrolling.cs:72:28:72:31 | access to parameter args | LoopUnrolling.cs:72:28:72:31 | access to parameter args |
|
||||
| LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | LoopUnrolling.cs:73:31:73:33 | access to local variable arg |
|
||||
| LoopUnrolling.cs:73:13:73:35 | ...; | LoopUnrolling.cs:73:13:73:35 | ...; |
|
||||
| LoopUnrolling.cs:73:31:73:33 | access to local variable arg | LoopUnrolling.cs:73:31:73:33 | access to local variable arg |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:23:3:23 | access to parameter i |
|
||||
| NullCoalescing.cs:3:23:3:28 | ... ?? ... | NullCoalescing.cs:3:23:3:28 | ... ?? ... |
|
||||
| NullCoalescing.cs:3:28:3:28 | 0 | NullCoalescing.cs:3:28:3:28 | 0 |
|
||||
|
||||
@@ -1372,6 +1372,153 @@
|
||||
| Initializers.cs:33:33:33:33 | access to parameter i | Initializers.cs:33:33:33:33 | access to parameter i | normal |
|
||||
| Initializers.cs:33:33:33:37 | ... + ... | Initializers.cs:33:33:33:37 | ... + ... | normal |
|
||||
| Initializers.cs:33:37:33:37 | access to parameter j | Initializers.cs:33:37:33:37 | access to parameter j | normal |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:10:13:10:19 | return ...; | return |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:9:13:9:28 | ... == ... | false |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:10:13:10:19 | return ...; | return |
|
||||
| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:9:13:9:16 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:9:13:9:23 | access to property Length | normal |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:9:13:9:28 | ... == ... | false |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:9:13:9:28 | ... == ... | true |
|
||||
| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:9:28:9:28 | 0 | normal |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:10:13:10:19 | return ...; | return |
|
||||
| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:11:21:11:23 | String arg | normal |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:28:11:31 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:12:31:12:33 | access to local variable arg | normal |
|
||||
| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:17:9:17:47 | ... ...; | LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:17:18:17:46 | 3 | LoopUnrolling.cs:17:18:17:46 | 3 | normal |
|
||||
| LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | LoopUnrolling.cs:17:30:17:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:17:30:17:46 | { ..., ... } | LoopUnrolling.cs:17:30:17:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:17:32:17:34 | "a" | LoopUnrolling.cs:17:32:17:34 | "a" | normal |
|
||||
| LoopUnrolling.cs:17:37:17:39 | "b" | LoopUnrolling.cs:17:37:17:39 | "b" | normal |
|
||||
| LoopUnrolling.cs:17:42:17:44 | "c" | LoopUnrolling.cs:17:42:17:44 | "c" | normal |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:18:21:18:21 | String x | normal |
|
||||
| LoopUnrolling.cs:18:26:18:27 | access to local variable xs | LoopUnrolling.cs:18:26:18:27 | access to local variable xs | normal |
|
||||
| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:19:31:19:31 | access to local variable x | normal |
|
||||
| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:24:22:24:24 | Char arg | normal |
|
||||
| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:24:29:24:32 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:25:26:25:29 | Char arg0 | normal |
|
||||
| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:25:34:25:37 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | normal |
|
||||
| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | normal |
|
||||
| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:31:29:31:29 | 0 | normal |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:32:21:32:21 | String x | normal |
|
||||
| LoopUnrolling.cs:32:26:32:27 | access to local variable xs | LoopUnrolling.cs:32:26:32:27 | access to local variable xs | normal |
|
||||
| LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:33:13:33:33 | ...; | LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:33:31:33:31 | access to local variable x | LoopUnrolling.cs:33:31:33:31 | access to local variable x | normal |
|
||||
| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:38:9:38:47 | ... ...; | LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:38:18:38:46 | 3 | LoopUnrolling.cs:38:18:38:46 | 3 | normal |
|
||||
| LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | LoopUnrolling.cs:38:30:38:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:38:30:38:46 | { ..., ... } | LoopUnrolling.cs:38:30:38:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:38:32:38:34 | "a" | LoopUnrolling.cs:38:32:38:34 | "a" | normal |
|
||||
| LoopUnrolling.cs:38:37:38:39 | "b" | LoopUnrolling.cs:38:37:38:39 | "b" | normal |
|
||||
| LoopUnrolling.cs:38:42:38:44 | "c" | LoopUnrolling.cs:38:42:38:44 | "c" | normal |
|
||||
| LoopUnrolling.cs:39:9:39:47 | ... ...; | LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | normal |
|
||||
| LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | normal |
|
||||
| LoopUnrolling.cs:39:18:39:46 | 3 | LoopUnrolling.cs:39:18:39:46 | 3 | normal |
|
||||
| LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | LoopUnrolling.cs:39:30:39:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:39:30:39:46 | { ..., ... } | LoopUnrolling.cs:39:30:39:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:39:32:39:34 | "0" | LoopUnrolling.cs:39:32:39:34 | "0" | normal |
|
||||
| LoopUnrolling.cs:39:37:39:39 | "1" | LoopUnrolling.cs:39:37:39:39 | "1" | normal |
|
||||
| LoopUnrolling.cs:39:42:39:44 | "2" | LoopUnrolling.cs:39:42:39:44 | "2" | normal |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:40:21:40:21 | String x | normal |
|
||||
| LoopUnrolling.cs:40:26:40:27 | access to local variable xs | LoopUnrolling.cs:40:26:40:27 | access to local variable xs | normal |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:41:25:41:25 | String y | normal |
|
||||
| LoopUnrolling.cs:41:30:41:31 | access to local variable ys | LoopUnrolling.cs:41:30:41:31 | access to local variable ys | normal |
|
||||
| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:42:35:42:35 | access to local variable x | normal |
|
||||
| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:42:35:42:39 | ... + ... | normal |
|
||||
| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:42:39:42:39 | access to local variable y | normal |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:48:9:52:9 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:51:13:51:23 | goto ...; | goto(Label) |
|
||||
| LoopUnrolling.cs:47:9:47:47 | ... ...; | LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:47:18:47:46 | 3 | LoopUnrolling.cs:47:18:47:46 | 3 | normal |
|
||||
| LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | LoopUnrolling.cs:47:30:47:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:47:30:47:46 | { ..., ... } | LoopUnrolling.cs:47:30:47:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:47:32:47:34 | "a" | LoopUnrolling.cs:47:32:47:34 | "a" | normal |
|
||||
| LoopUnrolling.cs:47:37:47:39 | "b" | LoopUnrolling.cs:47:37:47:39 | "b" | normal |
|
||||
| LoopUnrolling.cs:47:42:47:44 | "c" | LoopUnrolling.cs:47:42:47:44 | "c" | normal |
|
||||
| LoopUnrolling.cs:48:9:52:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:48:9:52:9 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:48:9:52:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:51:13:51:23 | goto ...; | goto(Label) |
|
||||
| LoopUnrolling.cs:48:21:48:21 | String x | LoopUnrolling.cs:48:21:48:21 | String x | normal |
|
||||
| LoopUnrolling.cs:48:26:48:27 | access to local variable xs | LoopUnrolling.cs:48:26:48:27 | access to local variable xs | normal |
|
||||
| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:51:13:51:23 | goto ...; | goto(Label) |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:50:13:50:17 | Label: | normal |
|
||||
| LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:50:20:50:40 | ...; | LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:50:38:50:38 | access to local variable x | LoopUnrolling.cs:50:38:50:38 | access to local variable x | normal |
|
||||
| LoopUnrolling.cs:51:13:51:23 | goto ...; | LoopUnrolling.cs:51:13:51:23 | goto ...; | goto(Label) |
|
||||
| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:58:9:64:9 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:57:9:57:47 | ... ...; | LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | normal |
|
||||
| LoopUnrolling.cs:57:18:57:46 | 3 | LoopUnrolling.cs:57:18:57:46 | 3 | normal |
|
||||
| LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | LoopUnrolling.cs:57:30:57:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:57:30:57:46 | { ..., ... } | LoopUnrolling.cs:57:30:57:46 | { ..., ... } | normal |
|
||||
| LoopUnrolling.cs:57:32:57:34 | "a" | LoopUnrolling.cs:57:32:57:34 | "a" | normal |
|
||||
| LoopUnrolling.cs:57:37:57:39 | "b" | LoopUnrolling.cs:57:37:57:39 | "b" | normal |
|
||||
| LoopUnrolling.cs:57:42:57:44 | "c" | LoopUnrolling.cs:57:42:57:44 | "c" | normal |
|
||||
| LoopUnrolling.cs:58:9:64:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:58:9:64:9 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:58:21:58:21 | String x | LoopUnrolling.cs:58:21:58:21 | String x | normal |
|
||||
| LoopUnrolling.cs:58:26:58:27 | access to local variable xs | LoopUnrolling.cs:58:26:58:27 | access to local variable xs | normal |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:62:17:62:17 | access to parameter b | false |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:63:17:63:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:60:17:60:17 | access to parameter b | false |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:61:17:61:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:60:17:60:17 | access to parameter b | false |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:60:17:60:17 | access to parameter b | true |
|
||||
| LoopUnrolling.cs:61:17:61:36 | call to method WriteLine | LoopUnrolling.cs:61:17:61:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:61:17:61:37 | ...; | LoopUnrolling.cs:61:17:61:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:61:35:61:35 | access to local variable x | LoopUnrolling.cs:61:35:61:35 | access to local variable x | normal |
|
||||
| LoopUnrolling.cs:62:13:63:37 | if (...) ... | LoopUnrolling.cs:62:17:62:17 | access to parameter b | false |
|
||||
| LoopUnrolling.cs:62:13:63:37 | if (...) ... | LoopUnrolling.cs:63:17:63:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:62:17:62:17 | access to parameter b | LoopUnrolling.cs:62:17:62:17 | access to parameter b | false |
|
||||
| LoopUnrolling.cs:62:17:62:17 | access to parameter b | LoopUnrolling.cs:62:17:62:17 | access to parameter b | true |
|
||||
| LoopUnrolling.cs:63:17:63:36 | call to method WriteLine | LoopUnrolling.cs:63:17:63:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:63:17:63:37 | ...; | LoopUnrolling.cs:63:17:63:36 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:63:35:63:35 | access to local variable x | LoopUnrolling.cs:63:35:63:35 | access to local variable x | normal |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:70:13:70:19 | return ...; | return |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:69:14:69:23 | call to method Any | false [true] |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:70:13:70:19 | return ...; | return |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:69:14:69:23 | call to method Any | false [true] |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:69:14:69:23 | call to method Any | true [false] |
|
||||
| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:69:14:69:17 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:69:14:69:23 | call to method Any | false |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:69:14:69:23 | call to method Any | true |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:70:13:70:19 | return ...; | return |
|
||||
| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:71:9:71:12 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:71:9:71:20 | call to method Clear | normal |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:20 | call to method Clear | normal |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | empty |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:72:21:72:23 | String arg | normal |
|
||||
| LoopUnrolling.cs:72:28:72:31 | access to parameter args | LoopUnrolling.cs:72:28:72:31 | access to parameter args | normal |
|
||||
| LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:73:13:73:35 | ...; | LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | normal |
|
||||
| LoopUnrolling.cs:73:31:73:33 | access to local variable arg | LoopUnrolling.cs:73:31:73:33 | access to local variable arg | normal |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:23:3:23 | access to parameter i | non-null |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:23:3:23 | access to parameter i | null |
|
||||
| NullCoalescing.cs:3:23:3:28 | ... ?? ... | NullCoalescing.cs:3:23:3:23 | access to parameter i | non-null |
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
class LoopUnrolling
|
||||
{
|
||||
void M1(string[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
return;
|
||||
foreach(var arg in args) // unroll
|
||||
Console.WriteLine(arg);
|
||||
}
|
||||
|
||||
void M2()
|
||||
{
|
||||
var xs = new string[]{ "a", "b", "c" };
|
||||
foreach(var x in xs) // unroll
|
||||
Console.WriteLine(x);
|
||||
}
|
||||
|
||||
void M3(string args)
|
||||
{
|
||||
foreach (var arg in args) // no unroll
|
||||
foreach (var arg0 in args) // unroll
|
||||
Console.WriteLine(arg0);
|
||||
}
|
||||
|
||||
void M4()
|
||||
{
|
||||
var xs = new string[0];
|
||||
foreach(var x in xs) // no unroll
|
||||
Console.WriteLine(x);
|
||||
}
|
||||
|
||||
void M5()
|
||||
{
|
||||
var xs = new string[]{ "a", "b", "c" };
|
||||
var ys = new string[]{ "0", "1", "2" };
|
||||
foreach(var x in xs) // unroll
|
||||
foreach(var y in ys) // unroll
|
||||
Console.WriteLine(x + y);
|
||||
}
|
||||
|
||||
void M6()
|
||||
{
|
||||
var xs = new string[]{ "a", "b", "c" };
|
||||
foreach(var x in xs) // unroll
|
||||
{
|
||||
Label: Console.WriteLine(x);
|
||||
goto Label;
|
||||
}
|
||||
}
|
||||
|
||||
void M7(bool b)
|
||||
{
|
||||
var xs = new string[]{ "a", "b", "c" };
|
||||
foreach(var x in xs) // unroll
|
||||
{
|
||||
if (b)
|
||||
Console.WriteLine(x);
|
||||
if (b)
|
||||
Console.WriteLine(x);
|
||||
}
|
||||
}
|
||||
|
||||
void M8(List<string> args)
|
||||
{
|
||||
if (!args.Any())
|
||||
return;
|
||||
args.Clear();
|
||||
foreach(var arg in args) // no unroll
|
||||
Console.WriteLine(arg);
|
||||
}
|
||||
}
|
||||
@@ -1447,6 +1447,172 @@
|
||||
| Initializers.cs:33:33:33:33 | access to parameter i | Initializers.cs:33:37:33:37 | access to parameter j | semmle.label | successor |
|
||||
| Initializers.cs:33:33:33:37 | ... + ... | Initializers.cs:33:29:33:37 | ... = ... | semmle.label | successor |
|
||||
| Initializers.cs:33:37:33:37 | access to parameter j | Initializers.cs:33:33:33:37 | ... + ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:8:5:13:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:9:9:10:19 | if (...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:9:13:9:16 | access to parameter args | semmle.label | successor |
|
||||
| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:9:13:9:23 | access to property Length | semmle.label | successor |
|
||||
| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:9:28:9:28 | 0 | semmle.label | successor |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:10:13:10:19 | return ...; | semmle.label | true |
|
||||
| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:11:28:11:31 | access to parameter args | semmle.label | false |
|
||||
| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:9:13:9:28 | ... == ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:7:10:7:11 | exit M1 | semmle.label | return |
|
||||
| LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | LoopUnrolling.cs:11:21:11:23 | String arg | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:7:10:7:11 | exit M1 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:11:21:11:23 | String arg | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:11:21:11:23 | String arg | LoopUnrolling.cs:12:13:12:35 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:11:28:11:31 | access to parameter args | LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:12:31:12:33 | access to local variable arg | semmle.label | successor |
|
||||
| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:16:5:20:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:17:9:17:47 | ... ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:9:17:47 | ... ...; | LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | LoopUnrolling.cs:18:26:18:27 | access to local variable xs | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:18:17:46 | array creation of type String[] | LoopUnrolling.cs:17:32:17:34 | "a" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:30:17:46 | { ..., ... } | LoopUnrolling.cs:17:13:17:46 | String[] xs = ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:32:17:34 | "a" | LoopUnrolling.cs:17:37:17:39 | "b" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:37:17:39 | "b" | LoopUnrolling.cs:17:42:17:44 | "c" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:17:42:17:44 | "c" | LoopUnrolling.cs:17:30:17:46 | { ..., ... } | semmle.label | successor |
|
||||
| LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | LoopUnrolling.cs:18:21:18:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:15:10:15:11 | exit M2 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:18:21:18:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:18:21:18:21 | String x | LoopUnrolling.cs:19:13:19:33 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:18:26:18:27 | access to local variable xs | LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:19:31:19:31 | access to local variable x | semmle.label | successor |
|
||||
| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:23:5:27:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:24:29:24:32 | access to parameter args | semmle.label | successor |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | exit M3 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:22:24:24 | Char arg | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:25:34:25:37 | access to parameter args | semmle.label | successor |
|
||||
| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | semmle.label | empty |
|
||||
| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:26:17:26:40 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | semmle.label | successor |
|
||||
| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:30:5:34:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:31:9:31:31 | ... ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:31:29:31:29 | 0 | semmle.label | successor |
|
||||
| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:32:26:32:27 | access to local variable xs | semmle.label | successor |
|
||||
| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | semmle.label | successor |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | exit M4 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:32:21:32:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:32:21:32:21 | String x | LoopUnrolling.cs:33:13:33:33 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:32:26:32:27 | access to local variable xs | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | LoopUnrolling.cs:32:9:33:33 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:33:13:33:33 | ...; | LoopUnrolling.cs:33:31:33:31 | access to local variable x | semmle.label | successor |
|
||||
| LoopUnrolling.cs:33:31:33:31 | access to local variable x | LoopUnrolling.cs:33:13:33:32 | call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:37:5:43:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:38:9:38:47 | ... ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:9:38:47 | ... ...; | LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | LoopUnrolling.cs:39:9:39:47 | ... ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:18:38:46 | array creation of type String[] | LoopUnrolling.cs:38:32:38:34 | "a" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:30:38:46 | { ..., ... } | LoopUnrolling.cs:38:13:38:46 | String[] xs = ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:32:38:34 | "a" | LoopUnrolling.cs:38:37:38:39 | "b" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:37:38:39 | "b" | LoopUnrolling.cs:38:42:38:44 | "c" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:38:42:38:44 | "c" | LoopUnrolling.cs:38:30:38:46 | { ..., ... } | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:9:39:47 | ... ...; | LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | LoopUnrolling.cs:40:26:40:27 | access to local variable xs | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:18:39:46 | array creation of type String[] | LoopUnrolling.cs:39:32:39:34 | "0" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:30:39:46 | { ..., ... } | LoopUnrolling.cs:39:13:39:46 | String[] ys = ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:32:39:34 | "0" | LoopUnrolling.cs:39:37:39:39 | "1" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:37:39:39 | "1" | LoopUnrolling.cs:39:42:39:44 | "2" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:39:42:39:44 | "2" | LoopUnrolling.cs:39:30:39:46 | { ..., ... } | semmle.label | successor |
|
||||
| LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | LoopUnrolling.cs:40:21:40:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | exit M5 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:21:40:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:40:21:40:21 | String x | LoopUnrolling.cs:41:30:41:31 | access to local variable ys | semmle.label | successor |
|
||||
| LoopUnrolling.cs:40:26:40:27 | access to local variable xs | LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | LoopUnrolling.cs:41:25:41:25 | String y | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | semmle.label | empty |
|
||||
| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:41:25:41:25 | String y | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:41:25:41:25 | String y | LoopUnrolling.cs:42:17:42:41 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:41:30:41:31 | access to local variable ys | LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:42:35:42:35 | access to local variable x | semmle.label | successor |
|
||||
| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:42:39:42:39 | access to local variable y | semmle.label | successor |
|
||||
| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:42:35:42:39 | ... + ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:46:5:53:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:47:9:47:47 | ... ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:9:47:47 | ... ...; | LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | LoopUnrolling.cs:48:26:48:27 | access to local variable xs | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:18:47:46 | array creation of type String[] | LoopUnrolling.cs:47:32:47:34 | "a" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:30:47:46 | { ..., ... } | LoopUnrolling.cs:47:13:47:46 | String[] xs = ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:32:47:34 | "a" | LoopUnrolling.cs:47:37:47:39 | "b" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:37:47:39 | "b" | LoopUnrolling.cs:47:42:47:44 | "c" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:47:42:47:44 | "c" | LoopUnrolling.cs:47:30:47:46 | { ..., ... } | semmle.label | successor |
|
||||
| LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | LoopUnrolling.cs:48:21:48:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:48:21:48:21 | String x | LoopUnrolling.cs:49:9:52:9 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:48:26:48:27 | access to local variable xs | LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:50:13:50:17 | Label: | semmle.label | successor |
|
||||
| LoopUnrolling.cs:50:13:50:17 | Label: | LoopUnrolling.cs:50:20:50:40 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | LoopUnrolling.cs:51:13:51:23 | goto ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:50:20:50:40 | ...; | LoopUnrolling.cs:50:38:50:38 | access to local variable x | semmle.label | successor |
|
||||
| LoopUnrolling.cs:50:38:50:38 | access to local variable x | LoopUnrolling.cs:50:20:50:39 | call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:51:13:51:23 | goto ...; | LoopUnrolling.cs:50:13:50:17 | Label: | semmle.label | goto(Label) |
|
||||
| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:56:5:65:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:57:9:57:47 | ... ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:9:57:47 | ... ...; | LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | LoopUnrolling.cs:58:26:58:27 | access to local variable xs | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:18:57:46 | array creation of type String[] | LoopUnrolling.cs:57:32:57:34 | "a" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:30:57:46 | { ..., ... } | LoopUnrolling.cs:57:13:57:46 | String[] xs = ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:32:57:34 | "a" | LoopUnrolling.cs:57:37:57:39 | "b" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:37:57:39 | "b" | LoopUnrolling.cs:57:42:57:44 | "c" | semmle.label | successor |
|
||||
| LoopUnrolling.cs:57:42:57:44 | "c" | LoopUnrolling.cs:57:30:57:46 | { ..., ... } | semmle.label | successor |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | exit M7 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | exit M7 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | LoopUnrolling.cs:58:21:58:21 | String x | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:58:21:58:21 | String x | LoopUnrolling.cs:59:9:64:9 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:58:26:58:27 | access to local variable xs | LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:60:13:61:37 | if (...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | semmle.label | successor |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | semmle.label | successor |
|
||||
| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:60:17:60:17 | access to parameter b | semmle.label | successor |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | semmle.label | false |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | semmle.label | true |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | semmle.label | true |
|
||||
| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | semmle.label | false |
|
||||
| LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | semmle.label | successor |
|
||||
| LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | semmle.label | successor |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | semmle.label | successor |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | semmle.label | false |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | semmle.label | true |
|
||||
| LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | semmle.label | successor |
|
||||
| LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | semmle.label | successor |
|
||||
| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:68:5:74:5 | {...} | semmle.label | successor |
|
||||
| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:69:9:70:19 | if (...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:69:13:69:23 | !... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:69:13:69:23 | !... | LoopUnrolling.cs:69:14:69:17 | access to parameter args | semmle.label | successor |
|
||||
| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:69:14:69:23 | call to method Any | semmle.label | successor |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:70:13:70:19 | return ...; | semmle.label | false |
|
||||
| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:71:9:71:21 | ...; | semmle.label | true |
|
||||
| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:67:10:67:11 | exit M8 | semmle.label | return |
|
||||
| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:71:9:71:20 | call to method Clear | semmle.label | successor |
|
||||
| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:72:28:72:31 | access to parameter args | semmle.label | successor |
|
||||
| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:12 | access to parameter args | semmle.label | successor |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:67:10:67:11 | exit M8 | semmle.label | empty |
|
||||
| LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:72:21:72:23 | String arg | semmle.label | non-empty |
|
||||
| LoopUnrolling.cs:72:21:72:23 | String arg | LoopUnrolling.cs:73:13:73:35 | ...; | semmle.label | successor |
|
||||
| LoopUnrolling.cs:72:28:72:31 | access to parameter args | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | LoopUnrolling.cs:72:9:73:35 | foreach (... ... in ...) ... | semmle.label | successor |
|
||||
| LoopUnrolling.cs:73:13:73:35 | ...; | LoopUnrolling.cs:73:31:73:33 | access to local variable arg | semmle.label | successor |
|
||||
| LoopUnrolling.cs:73:31:73:33 | access to local variable arg | LoopUnrolling.cs:73:13:73:34 | call to method WriteLine | semmle.label | successor |
|
||||
| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:23:3:28 | ... ?? ... | semmle.label | successor |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:9:3:10 | exit M1 | semmle.label | non-null |
|
||||
| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:28:3:28 | 0 | semmle.label | null |
|
||||
|
||||
@@ -222,6 +222,26 @@ booleanNode
|
||||
| Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Field2 (line 129): true |
|
||||
| Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Field1 (line 129): true |
|
||||
| Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Field2 (line 129): true |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | b (line 55): false |
|
||||
| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | b (line 55): true |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): false] String x | b (line 55): false |
|
||||
| LoopUnrolling.cs:58:21:58:21 | [b (line 55): true] String x | b (line 55): true |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | b (line 55): false |
|
||||
| LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | b (line 55): true |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | b (line 55): false |
|
||||
| LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | b (line 55): true |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | b (line 55): false |
|
||||
| LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | b (line 55): true |
|
||||
| LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | b (line 55): true |
|
||||
| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | b (line 55): true |
|
||||
| LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | b (line 55): true |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | b (line 55): false |
|
||||
| LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | b (line 55): true |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | b (line 55): false |
|
||||
| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | b (line 55): true |
|
||||
| LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | b (line 55): true |
|
||||
| LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | b (line 55): true |
|
||||
| LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | b (line 55): true |
|
||||
finallyNode
|
||||
| BreakInTry.cs:30:13:33:13 | [finally: break] {...} | BreakInTry.cs:24:13:33:13 | try {...} ... |
|
||||
| BreakInTry.cs:31:17:32:21 | [finally: break] if (...) ... | BreakInTry.cs:24:13:33:13 | try {...} ... |
|
||||
@@ -621,6 +641,14 @@ entryPoint
|
||||
| Initializers.cs:29:9:29:11 | Sub | Initializers.cs:29:17:29:20 | call to constructor NoConstructor |
|
||||
| Initializers.cs:31:9:31:11 | Sub | Initializers.cs:31:22:31:25 | call to constructor Sub |
|
||||
| Initializers.cs:33:9:33:11 | Sub | Initializers.cs:20:23:20:23 | this access |
|
||||
| LoopUnrolling.cs:7:10:7:11 | M1 | LoopUnrolling.cs:8:5:13:5 | {...} |
|
||||
| LoopUnrolling.cs:15:10:15:11 | M2 | LoopUnrolling.cs:16:5:20:5 | {...} |
|
||||
| LoopUnrolling.cs:22:10:22:11 | M3 | LoopUnrolling.cs:23:5:27:5 | {...} |
|
||||
| LoopUnrolling.cs:29:10:29:11 | M4 | LoopUnrolling.cs:30:5:34:5 | {...} |
|
||||
| LoopUnrolling.cs:36:10:36:11 | M5 | LoopUnrolling.cs:37:5:43:5 | {...} |
|
||||
| LoopUnrolling.cs:45:10:45:11 | M6 | LoopUnrolling.cs:46:5:53:5 | {...} |
|
||||
| LoopUnrolling.cs:55:10:55:11 | M7 | LoopUnrolling.cs:56:5:65:5 | {...} |
|
||||
| LoopUnrolling.cs:67:10:67:11 | M8 | LoopUnrolling.cs:68:5:74:5 | {...} |
|
||||
| NullCoalescing.cs:3:9:3:10 | M1 | NullCoalescing.cs:3:23:3:28 | ... ?? ... |
|
||||
| NullCoalescing.cs:5:9:5:10 | M2 | NullCoalescing.cs:5:24:5:43 | ... ? ... : ... |
|
||||
| NullCoalescing.cs:7:12:7:13 | M3 | NullCoalescing.cs:7:40:7:53 | ... ?? ... |
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
abstractValue
|
||||
| 0 | Collections.cs:12:32:12:32 | 0 |
|
||||
| 0 | Collections.cs:14:28:14:28 | 0 |
|
||||
| 0 | Collections.cs:16:27:16:27 | 0 |
|
||||
| 0 | Collections.cs:17:28:17:28 | 0 |
|
||||
| 0 | Collections.cs:23:31:23:31 | 0 |
|
||||
| 0 | Collections.cs:25:27:25:27 | 0 |
|
||||
| 0 | Collections.cs:27:26:27:26 | 0 |
|
||||
| 0 | Collections.cs:28:27:28:27 | 0 |
|
||||
| 0 | Collections.cs:34:33:34:33 | 0 |
|
||||
| 0 | Collections.cs:36:29:36:29 | 0 |
|
||||
| 0 | Collections.cs:38:28:38:28 | 0 |
|
||||
| 0 | Collections.cs:39:29:39:29 | 0 |
|
||||
| 0 | Collections.cs:50:27:50:27 | 0 |
|
||||
| 0 | Collections.cs:57:24:57:24 | 0 |
|
||||
| 0 | Collections.cs:65:24:65:24 | 0 |
|
||||
| 0 | Collections.cs:76:36:76:36 | 0 |
|
||||
| 0 | Collections.cs:78:36:78:36 | 0 |
|
||||
| 0 | Collections.cs:80:35:80:35 | 0 |
|
||||
| 0 | Collections.cs:81:36:81:36 | 0 |
|
||||
| 0 | Collections.cs:87:17:87:31 | 0 |
|
||||
| 0 | Guards.cs:12:24:12:24 | 0 |
|
||||
| 0 | Guards.cs:78:26:78:26 | 0 |
|
||||
| 0 | Guards.cs:80:25:80:25 | 0 |
|
||||
| 0 | Guards.cs:82:26:82:26 | 0 |
|
||||
| 0 | Guards.cs:92:30:92:30 | 0 |
|
||||
| 0 | Guards.cs:241:17:241:17 | 0 |
|
||||
| 0 | Guards.cs:255:17:255:19 | access to constant A |
|
||||
| 0 | Guards.cs:298:21:298:21 | 0 |
|
||||
| 0 | Guards.cs:310:21:310:21 | 0 |
|
||||
| 0 | Guards.cs:317:17:317:17 | 0 |
|
||||
| 0 | Guards.cs:322:18:322:18 | 0 |
|
||||
| 0 | Guards.cs:329:17:329:19 | access to constant A |
|
||||
| 0 | Guards.cs:334:20:334:20 | 0 |
|
||||
| 0 | Splitting.cs:136:20:136:20 | 0 |
|
||||
| 1 | Collections.cs:13:28:13:28 | 1 |
|
||||
| 1 | Collections.cs:15:28:15:28 | 1 |
|
||||
| 1 | Collections.cs:18:28:18:28 | 1 |
|
||||
| 1 | Collections.cs:24:27:24:27 | 1 |
|
||||
| 1 | Collections.cs:26:27:26:27 | 1 |
|
||||
| 1 | Collections.cs:29:27:29:27 | 1 |
|
||||
| 1 | Collections.cs:35:29:35:29 | 1 |
|
||||
| 1 | Collections.cs:37:29:37:29 | 1 |
|
||||
| 1 | Collections.cs:40:29:40:29 | 1 |
|
||||
| 1 | Collections.cs:77:36:77:36 | 1 |
|
||||
| 1 | Collections.cs:79:36:79:36 | 1 |
|
||||
| 1 | Collections.cs:82:36:82:36 | 1 |
|
||||
| 1 | Collections.cs:89:13:89:32 | 1 |
|
||||
| 1 | Guards.cs:92:25:92:25 | 1 |
|
||||
| 1 | Guards.cs:243:17:243:17 | 1 |
|
||||
| 1 | Guards.cs:246:18:246:18 | 1 |
|
||||
| 1 | Guards.cs:257:17:257:19 | access to constant B |
|
||||
| 1 | Guards.cs:260:18:260:20 | access to constant B |
|
||||
| 1 | Guards.cs:299:18:299:18 | 1 |
|
||||
| 1 | Guards.cs:311:18:311:18 | 1 |
|
||||
| 1 | Guards.cs:319:17:319:17 | 1 |
|
||||
| 1 | Guards.cs:322:13:322:13 | 1 |
|
||||
| 1 | Guards.cs:323:18:323:18 | 1 |
|
||||
| 1 | Guards.cs:331:17:331:19 | access to constant B |
|
||||
| 1 | Guards.cs:334:13:334:15 | access to constant B |
|
||||
| 1 | Guards.cs:335:18:335:18 | 1 |
|
||||
| 3 | Collections.cs:55:13:55:41 | 3 |
|
||||
| 3 | Collections.cs:63:17:63:45 | 3 |
|
||||
| 10 | Guards.cs:84:25:84:26 | 10 |
|
||||
| 10 | Guards.cs:86:26:86:27 | 10 |
|
||||
| empty | Collections.cs:54:13:54:16 | access to parameter args |
|
||||
| empty | Collections.cs:57:9:57:25 | ... = ... |
|
||||
| empty | Collections.cs:57:13:57:25 | array creation of type String[] |
|
||||
| empty | Collections.cs:58:9:58:13 | ... = ... |
|
||||
| empty | Collections.cs:58:13:58:13 | access to local variable x |
|
||||
| empty | Collections.cs:65:13:65:13 | access to local variable x |
|
||||
| empty | Collections.cs:87:17:87:31 | array creation of type String[] |
|
||||
| empty | Collections.cs:87:30:87:31 | { ..., ... } |
|
||||
| empty | Collections.cs:88:22:88:23 | { ..., ... } |
|
||||
| false | Guards.cs:178:16:178:20 | false |
|
||||
| false | Guards.cs:181:52:181:56 | false |
|
||||
| false | Guards.cs:217:18:217:22 | false |
|
||||
| false | Guards.cs:228:18:228:22 | false |
|
||||
| false | Guards.cs:295:18:295:22 | false |
|
||||
| false | Guards.cs:305:18:305:22 | false |
|
||||
| non-empty | Collections.cs:55:9:55:41 | ... = ... |
|
||||
| non-empty | Collections.cs:55:13:55:41 | array creation of type String[] |
|
||||
| non-empty | Collections.cs:55:25:55:41 | { ..., ... } |
|
||||
| non-empty | Collections.cs:56:9:56:13 | ... = ... |
|
||||
| non-empty | Collections.cs:56:13:56:13 | access to local variable x |
|
||||
| non-empty | Collections.cs:63:17:63:45 | array creation of type String[] |
|
||||
| non-empty | Collections.cs:63:29:63:45 | { ..., ... } |
|
||||
| non-empty | Collections.cs:68:13:68:13 | access to local variable x |
|
||||
| non-empty | Collections.cs:89:9:89:32 | ... = ... |
|
||||
| non-empty | Collections.cs:89:13:89:32 | array creation of type String[] |
|
||||
| non-empty | Collections.cs:89:26:89:32 | { ..., ... } |
|
||||
| non-empty | Collections.cs:90:22:90:28 | { ..., ... } |
|
||||
| non-null | Assert.cs:9:31:9:32 | "" |
|
||||
| non-null | Assert.cs:16:31:16:32 | "" |
|
||||
| non-null | Assert.cs:23:31:23:32 | "" |
|
||||
| non-null | Assert.cs:30:31:30:32 | "" |
|
||||
| non-null | Assert.cs:37:31:37:32 | "" |
|
||||
| non-null | Assert.cs:44:31:44:32 | "" |
|
||||
| non-null | Assert.cs:51:31:51:32 | "" |
|
||||
| non-null | Assert.cs:58:31:58:32 | "" |
|
||||
| non-null | Assert.cs:65:31:65:32 | "" |
|
||||
| non-null | Assert.cs:72:31:72:32 | "" |
|
||||
| non-null | Assert.cs:79:31:79:32 | "" |
|
||||
| non-null | Collections.cs:55:9:55:41 | ... = ... |
|
||||
| non-null | Collections.cs:55:13:55:41 | array creation of type String[] |
|
||||
| non-null | Collections.cs:55:27:55:29 | "a" |
|
||||
| non-null | Collections.cs:55:32:55:34 | "b" |
|
||||
| non-null | Collections.cs:55:37:55:39 | "c" |
|
||||
| non-null | Collections.cs:56:9:56:13 | ... = ... |
|
||||
| non-null | Collections.cs:56:13:56:13 | access to local variable x |
|
||||
| non-null | Collections.cs:57:9:57:25 | ... = ... |
|
||||
| non-null | Collections.cs:57:13:57:25 | array creation of type String[] |
|
||||
| non-null | Collections.cs:58:9:58:13 | ... = ... |
|
||||
| non-null | Collections.cs:58:13:58:13 | access to local variable x |
|
||||
| non-null | Collections.cs:63:17:63:45 | array creation of type String[] |
|
||||
| non-null | Collections.cs:63:31:63:33 | "a" |
|
||||
| non-null | Collections.cs:63:36:63:38 | "b" |
|
||||
| non-null | Collections.cs:63:41:63:43 | "c" |
|
||||
| non-null | Collections.cs:67:19:67:21 | "a" |
|
||||
| non-null | Collections.cs:68:19:68:21 | "b" |
|
||||
| non-null | Collections.cs:74:40:74:41 | "" |
|
||||
| non-null | Collections.cs:87:17:87:31 | array creation of type String[] |
|
||||
| non-null | Collections.cs:88:22:88:23 | array creation of type String[] |
|
||||
| non-null | Collections.cs:89:9:89:32 | ... = ... |
|
||||
| non-null | Collections.cs:89:13:89:32 | array creation of type String[] |
|
||||
| non-null | Collections.cs:89:28:89:30 | "a" |
|
||||
| non-null | Collections.cs:90:22:90:28 | array creation of type String[] |
|
||||
| non-null | Collections.cs:90:24:90:26 | "a" |
|
||||
| non-null | Guards.cs:18:31:18:46 | "<empty string>" |
|
||||
| non-null | Guards.cs:33:31:33:35 | ... + ... |
|
||||
| non-null | Guards.cs:36:32:36:36 | ... + ... |
|
||||
| non-null | Guards.cs:39:31:39:35 | ... + ... |
|
||||
| non-null | Guards.cs:42:32:42:36 | ... + ... |
|
||||
| non-null | Guards.cs:44:13:44:17 | this access |
|
||||
| non-null | Guards.cs:45:31:45:42 | object creation of type Guards |
|
||||
| non-null | Guards.cs:47:13:47:17 | this access |
|
||||
| non-null | Guards.cs:48:31:48:34 | this access |
|
||||
| non-null | Guards.cs:61:19:61:33 | object creation of type Exception |
|
||||
| non-null | Guards.cs:78:26:78:26 | (...) ... |
|
||||
| non-null | Guards.cs:80:25:80:25 | (...) ... |
|
||||
| non-null | Guards.cs:82:26:82:26 | (...) ... |
|
||||
| non-null | Guards.cs:84:25:84:26 | (...) ... |
|
||||
| non-null | Guards.cs:86:26:86:27 | (...) ... |
|
||||
| non-null | Guards.cs:92:25:92:25 | (...) ... |
|
||||
| non-null | Guards.cs:92:30:92:30 | (...) ... |
|
||||
| non-null | Guards.cs:96:18:96:19 | "" |
|
||||
| non-null | Guards.cs:105:19:105:33 | object creation of type Exception |
|
||||
| non-null | Guards.cs:183:37:183:48 | this access |
|
||||
| non-null | Guards.cs:189:14:189:25 | this access |
|
||||
| non-null | Guards.cs:191:14:191:25 | this access |
|
||||
| non-null | Guards.cs:193:14:193:25 | this access |
|
||||
| non-null | Guards.cs:195:13:195:27 | this access |
|
||||
| non-null | Guards.cs:197:14:197:29 | this access |
|
||||
| non-null | Guards.cs:268:30:268:41 | call to method GetType |
|
||||
| non-null | Splitting.cs:33:24:33:25 | "" |
|
||||
| non-null | Splitting.cs:132:21:132:29 | this access |
|
||||
| null | Assert.cs:9:24:9:27 | null |
|
||||
| null | Assert.cs:10:27:10:30 | null |
|
||||
| null | Assert.cs:16:24:16:27 | null |
|
||||
| null | Assert.cs:23:24:23:27 | null |
|
||||
| null | Assert.cs:30:24:30:27 | null |
|
||||
| null | Assert.cs:31:28:31:31 | null |
|
||||
| null | Assert.cs:37:24:37:27 | null |
|
||||
| null | Assert.cs:38:28:38:31 | null |
|
||||
| null | Assert.cs:44:24:44:27 | null |
|
||||
| null | Assert.cs:45:29:45:32 | null |
|
||||
| null | Assert.cs:51:24:51:27 | null |
|
||||
| null | Assert.cs:52:29:52:32 | null |
|
||||
| null | Assert.cs:58:24:58:27 | null |
|
||||
| null | Assert.cs:59:28:59:31 | null |
|
||||
| null | Assert.cs:65:24:65:27 | null |
|
||||
| null | Assert.cs:66:29:66:32 | null |
|
||||
| null | Assert.cs:72:24:72:27 | null |
|
||||
| null | Assert.cs:73:28:73:31 | null |
|
||||
| null | Assert.cs:79:24:79:27 | null |
|
||||
| null | Assert.cs:80:29:80:32 | null |
|
||||
| null | Guards.cs:10:21:10:24 | null |
|
||||
| null | Guards.cs:24:18:24:21 | null |
|
||||
| null | Guards.cs:32:47:32:50 | null |
|
||||
| null | Guards.cs:35:18:35:21 | null |
|
||||
| null | Guards.cs:35:31:35:34 | null |
|
||||
| null | Guards.cs:38:20:38:23 | null |
|
||||
| null | Guards.cs:38:33:38:36 | null |
|
||||
| null | Guards.cs:41:22:41:25 | null |
|
||||
| null | Guards.cs:41:35:41:38 | null |
|
||||
| null | Guards.cs:44:22:44:25 | null |
|
||||
| null | Guards.cs:47:22:47:25 | null |
|
||||
| null | Guards.cs:53:24:53:27 | null |
|
||||
| null | Guards.cs:60:42:60:45 | null |
|
||||
| null | Guards.cs:68:21:68:24 | null |
|
||||
| null | Guards.cs:71:13:71:20 | ... = ... |
|
||||
| null | Guards.cs:71:17:71:20 | null |
|
||||
| null | Guards.cs:72:31:72:31 | access to parameter s |
|
||||
| null | Guards.cs:88:26:88:29 | null |
|
||||
| null | Guards.cs:104:42:104:45 | null |
|
||||
| null | Guards.cs:106:9:106:25 | ... = ... |
|
||||
| null | Guards.cs:106:22:106:25 | null |
|
||||
| null | Guards.cs:115:52:115:55 | null |
|
||||
| null | Guards.cs:117:9:117:25 | ... = ... |
|
||||
| null | Guards.cs:117:22:117:25 | null |
|
||||
| null | Guards.cs:172:38:172:41 | null |
|
||||
| null | Guards.cs:181:38:181:41 | null |
|
||||
| null | Guards.cs:185:42:185:45 | null |
|
||||
| null | Guards.cs:203:18:203:21 | null |
|
||||
| null | Splitting.cs:12:22:12:25 | null |
|
||||
| null | Splitting.cs:22:22:22:25 | null |
|
||||
| null | Splitting.cs:32:22:32:25 | null |
|
||||
| null | Splitting.cs:41:18:41:21 | null |
|
||||
| null | Splitting.cs:54:18:54:21 | null |
|
||||
| null | Splitting.cs:65:18:65:21 | null |
|
||||
| null | Splitting.cs:76:18:76:21 | null |
|
||||
| null | Splitting.cs:87:31:87:34 | null |
|
||||
| null | Splitting.cs:97:31:97:34 | null |
|
||||
| null | Splitting.cs:105:27:105:30 | null |
|
||||
| null | Splitting.cs:116:27:116:30 | null |
|
||||
| null | Splitting.cs:125:20:125:23 | null |
|
||||
| null | Splitting.cs:128:22:128:25 | null |
|
||||
| true | Guards.cs:177:20:177:23 | true |
|
||||
| true | Guards.cs:181:45:181:48 | true |
|
||||
| true | Guards.cs:185:49:185:52 | true |
|
||||
| true | Guards.cs:185:56:185:59 | true |
|
||||
| true | Guards.cs:215:18:215:21 | true |
|
||||
| true | Guards.cs:220:18:220:21 | true |
|
||||
| true | Guards.cs:230:18:230:21 | true |
|
||||
| true | Guards.cs:233:18:233:21 | true |
|
||||
| true | Guards.cs:293:18:293:21 | true |
|
||||
| true | Guards.cs:298:13:298:16 | true |
|
||||
| true | Guards.cs:307:18:307:21 | true |
|
||||
| true | Guards.cs:310:13:310:16 | true |
|
||||
dualValue
|
||||
| empty | non-empty |
|
||||
| false | true |
|
||||
| match 1 | non-match 1 |
|
||||
| match 1 | non-match 1 |
|
||||
| match "" | non-match "" |
|
||||
| match "" | non-match "" |
|
||||
| match Action<String> a | non-match Action<String> a |
|
||||
| match Action<String> a | non-match Action<String> a |
|
||||
| match _ | non-match _ |
|
||||
| match _ | non-match _ |
|
||||
| match _ | non-match _ |
|
||||
| match _ | non-match _ |
|
||||
| match _ | non-match _ |
|
||||
| match access to constant B | non-match access to constant B |
|
||||
| match access to constant B | non-match access to constant B |
|
||||
| match access to type Action<Object> | non-match access to type Action<Object> |
|
||||
| match access to type Action<Object> | non-match access to type Action<Object> |
|
||||
| match null | non-match null |
|
||||
| match null | non-match null |
|
||||
| match true | non-match true |
|
||||
| match true | non-match true |
|
||||
| match true | non-match true |
|
||||
| match true | non-match true |
|
||||
| non-empty | empty |
|
||||
| non-match 1 | match 1 |
|
||||
| non-match 1 | match 1 |
|
||||
| non-match "" | match "" |
|
||||
| non-match "" | match "" |
|
||||
| non-match Action<String> a | match Action<String> a |
|
||||
| non-match Action<String> a | match Action<String> a |
|
||||
| non-match _ | match _ |
|
||||
| non-match _ | match _ |
|
||||
| non-match _ | match _ |
|
||||
| non-match _ | match _ |
|
||||
| non-match _ | match _ |
|
||||
| non-match access to constant B | match access to constant B |
|
||||
| non-match access to constant B | match access to constant B |
|
||||
| non-match access to type Action<Object> | match access to type Action<Object> |
|
||||
| non-match access to type Action<Object> | match access to type Action<Object> |
|
||||
| non-match null | match null |
|
||||
| non-match null | match null |
|
||||
| non-match true | match true |
|
||||
| non-match true | match true |
|
||||
| non-match true | match true |
|
||||
| non-match true | match true |
|
||||
| non-null | null |
|
||||
| null | non-null |
|
||||
| true | false |
|
||||
singletonValue
|
||||
| 0 |
|
||||
| 1 |
|
||||
| 3 |
|
||||
| 10 |
|
||||
| false |
|
||||
| null |
|
||||
| true |
|
||||
@@ -0,0 +1,8 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
query predicate abstractValue(AbstractValue value, Expr e) { e = value.getAnExpr() }
|
||||
|
||||
query predicate dualValue(AbstractValue value, AbstractValue dual) { dual = value.getDualValue() }
|
||||
|
||||
query predicate singletonValue(AbstractValue value) { value.isSingleton() }
|
||||
@@ -15,6 +15,11 @@
|
||||
| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false |
|
||||
| Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:54:13:54:16 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
|
||||
| Collections.cs:68:13:68:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:12:13:12:24 | ... > ... | Guards.cs:12:13:12:13 | access to parameter s | true |
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// semmle-extractor-options: /r:System.Collections.Specialized.dll /r:System.Collections.dll /r:System.Linq.dll
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
|
||||
public class Collections
|
||||
{
|
||||
void M1(string[] args)
|
||||
{
|
||||
var b = args.Length == 0;
|
||||
b = args.Length == 1;
|
||||
b = args.Length != 0;
|
||||
b = args.Length != 1;
|
||||
b = args.Length > 0;
|
||||
b = args.Length >= 0;
|
||||
b = args.Length >= 1;
|
||||
}
|
||||
|
||||
void M2(ICollection<string> args)
|
||||
{
|
||||
var b = args.Count == 0;
|
||||
b = args.Count == 1;
|
||||
b = args.Count != 0;
|
||||
b = args.Count != 1;
|
||||
b = args.Count > 0;
|
||||
b = args.Count >= 0;
|
||||
b = args.Count >= 1;
|
||||
}
|
||||
|
||||
void M3(string[] args)
|
||||
{
|
||||
var b = args.Count() == 0;
|
||||
b = args.Count() == 1;
|
||||
b = args.Count() != 0;
|
||||
b = args.Count() != 1;
|
||||
b = args.Count() > 0;
|
||||
b = args.Count() >= 0;
|
||||
b = args.Count() >= 1;
|
||||
}
|
||||
|
||||
void M4(string[] args)
|
||||
{
|
||||
var b = args.Any();
|
||||
}
|
||||
|
||||
void M5(List<string> args)
|
||||
{
|
||||
if (args.Count == 0)
|
||||
return;
|
||||
var x = args.ToArray();
|
||||
args.Clear();
|
||||
x = args.ToArray();
|
||||
x = new string[]{ "a", "b", "c" };
|
||||
x = x;
|
||||
x = new string[0];
|
||||
x = x;
|
||||
}
|
||||
|
||||
void M6()
|
||||
{
|
||||
var x = new string[]{ "a", "b", "c" }.ToList();
|
||||
x.Clear();
|
||||
if (x.Count == 0)
|
||||
{
|
||||
x.Add("a");
|
||||
x.Add("b");
|
||||
}
|
||||
}
|
||||
|
||||
void M7(string[] args)
|
||||
{
|
||||
bool IsEmpty(string s) => s == "";
|
||||
var b = args.Any(IsEmpty);
|
||||
b = args.Count(IsEmpty) == 0;
|
||||
b = args.Count(IsEmpty) == 1;
|
||||
b = args.Count(IsEmpty) != 0;
|
||||
b = args.Count(IsEmpty) != 1;
|
||||
b = args.Count(IsEmpty) > 0;
|
||||
b = args.Count(IsEmpty) >= 0;
|
||||
b = args.Count(IsEmpty) >= 1;
|
||||
}
|
||||
|
||||
void M8()
|
||||
{
|
||||
var x = new string[] {};
|
||||
string[] y = {};
|
||||
x = new string[] { "a" };
|
||||
string[] z = { "a" };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
| Collections.cs:12:17:12:32 | ... == ... | Collections.cs:12:17:12:20 | access to parameter args | false | false |
|
||||
| Collections.cs:12:17:12:32 | ... == ... | Collections.cs:12:17:12:20 | access to parameter args | true | true |
|
||||
| Collections.cs:13:13:13:28 | ... == ... | Collections.cs:13:13:13:16 | access to parameter args | true | false |
|
||||
| Collections.cs:14:13:14:28 | ... != ... | Collections.cs:14:13:14:16 | access to parameter args | false | true |
|
||||
| Collections.cs:14:13:14:28 | ... != ... | Collections.cs:14:13:14:16 | access to parameter args | true | false |
|
||||
| Collections.cs:15:13:15:28 | ... != ... | Collections.cs:15:13:15:16 | access to parameter args | false | false |
|
||||
| Collections.cs:16:13:16:27 | ... > ... | Collections.cs:16:13:16:16 | access to parameter args | true | false |
|
||||
| Collections.cs:18:13:18:28 | ... >= ... | Collections.cs:18:13:18:16 | access to parameter args | true | false |
|
||||
| Collections.cs:23:17:23:31 | ... == ... | Collections.cs:23:17:23:20 | access to parameter args | false | false |
|
||||
| Collections.cs:23:17:23:31 | ... == ... | Collections.cs:23:17:23:20 | access to parameter args | true | true |
|
||||
| Collections.cs:24:13:24:27 | ... == ... | Collections.cs:24:13:24:16 | access to parameter args | true | false |
|
||||
| Collections.cs:25:13:25:27 | ... != ... | Collections.cs:25:13:25:16 | access to parameter args | false | true |
|
||||
| Collections.cs:25:13:25:27 | ... != ... | Collections.cs:25:13:25:16 | access to parameter args | true | false |
|
||||
| Collections.cs:26:13:26:27 | ... != ... | Collections.cs:26:13:26:16 | access to parameter args | false | false |
|
||||
| Collections.cs:27:13:27:26 | ... > ... | Collections.cs:27:13:27:16 | access to parameter args | true | false |
|
||||
| Collections.cs:29:13:29:27 | ... >= ... | Collections.cs:29:13:29:16 | access to parameter args | true | false |
|
||||
| Collections.cs:34:17:34:33 | ... == ... | Collections.cs:34:17:34:20 | access to parameter args | false | false |
|
||||
| Collections.cs:34:17:34:33 | ... == ... | Collections.cs:34:17:34:20 | access to parameter args | true | true |
|
||||
| Collections.cs:35:13:35:29 | ... == ... | Collections.cs:35:13:35:16 | access to parameter args | true | false |
|
||||
| Collections.cs:36:13:36:29 | ... != ... | Collections.cs:36:13:36:16 | access to parameter args | false | true |
|
||||
| Collections.cs:36:13:36:29 | ... != ... | Collections.cs:36:13:36:16 | access to parameter args | true | false |
|
||||
| Collections.cs:37:13:37:29 | ... != ... | Collections.cs:37:13:37:16 | access to parameter args | false | false |
|
||||
| Collections.cs:38:13:38:28 | ... > ... | Collections.cs:38:13:38:16 | access to parameter args | true | false |
|
||||
| Collections.cs:40:13:40:29 | ... >= ... | Collections.cs:40:13:40:16 | access to parameter args | true | false |
|
||||
| Collections.cs:45:17:45:26 | call to method Any | Collections.cs:45:17:45:20 | access to parameter args | false | true |
|
||||
| Collections.cs:45:17:45:26 | call to method Any | Collections.cs:45:17:45:20 | access to parameter args | true | false |
|
||||
| Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | false |
|
||||
| Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | true | true |
|
||||
| Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | false | false |
|
||||
| Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true | true |
|
||||
| Collections.cs:75:17:75:33 | call to method Any | Collections.cs:75:17:75:20 | access to parameter args | true | false |
|
||||
| Collections.cs:76:13:76:36 | ... == ... | Collections.cs:76:13:76:16 | access to parameter args | false | false |
|
||||
| Collections.cs:77:13:77:36 | ... == ... | Collections.cs:77:13:77:16 | access to parameter args | true | false |
|
||||
| Collections.cs:78:13:78:36 | ... != ... | Collections.cs:78:13:78:16 | access to parameter args | true | false |
|
||||
| Collections.cs:79:13:79:36 | ... != ... | Collections.cs:79:13:79:16 | access to parameter args | false | false |
|
||||
| Collections.cs:80:13:80:35 | ... > ... | Collections.cs:80:13:80:16 | access to parameter args | true | false |
|
||||
| Collections.cs:82:13:82:36 | ... >= ... | Collections.cs:82:13:82:16 | access to parameter args | true | false |
|
||||
@@ -0,0 +1,6 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
query predicate emptinessCheck(Expr check, CollectionExpr collection, AbstractValue v, boolean isEmpty) {
|
||||
check = collection.getAnEmptinessCheck(v, isEmpty)
|
||||
}
|
||||
@@ -30,6 +30,13 @@
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | null |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false |
|
||||
| Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:54:13:54:16 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:13 | access to local variable x | Collections.cs:65:13:65:13 | access to local variable x | empty |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
|
||||
| Collections.cs:68:13:68:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
|
||||
@@ -30,6 +30,13 @@
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | null |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false |
|
||||
| Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:54:13:54:16 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:13 | access to local variable x | Collections.cs:65:13:65:13 | access to local variable x | empty |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
|
||||
| Collections.cs:68:13:68:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
|
||||
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | Guards.cs:10:16:10:16 | access to parameter s | non-null |
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
| Assert.cs:9:16:9:32 | String s = ... | non-null | Assert.cs:9:16:9:16 | access to local variable s | non-null |
|
||||
| Assert.cs:9:16:9:32 | String s = ... | null | Assert.cs:9:16:9:16 | access to local variable s | null |
|
||||
| Assert.cs:9:20:9:32 | ... ? ... : ... | non-null | Assert.cs:9:20:9:20 | access to parameter b | false |
|
||||
| Assert.cs:9:20:9:32 | ... ? ... : ... | non-null | Assert.cs:9:31:9:32 | "" | non-null |
|
||||
| Assert.cs:9:20:9:32 | ... ? ... : ... | null | Assert.cs:9:20:9:20 | access to parameter b | true |
|
||||
| Assert.cs:9:20:9:32 | ... ? ... : ... | null | Assert.cs:9:24:9:27 | null | null |
|
||||
| Assert.cs:10:22:10:22 | access to local variable s | empty | Assert.cs:9:20:9:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:10:22:10:22 | access to local variable s | non-empty | Assert.cs:9:20:9:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:10:22:10:22 | access to local variable s | non-null | Assert.cs:9:20:9:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:10:22:10:22 | access to local variable s | null | Assert.cs:9:20:9:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:10:22:10:30 | ... != ... | false | Assert.cs:9:20:9:20 | access to parameter b | true |
|
||||
@@ -12,32 +12,32 @@
|
||||
| Assert.cs:10:22:10:30 | ... != ... | true | Assert.cs:10:22:10:22 | access to local variable s | non-null |
|
||||
| Assert.cs:11:27:11:27 | access to local variable s | non-null | Assert.cs:9:20:9:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:11:27:11:27 | access to local variable s | null | Assert.cs:9:20:9:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:16:16:16:32 | String s = ... | non-null | Assert.cs:16:16:16:16 | access to local variable s | non-null |
|
||||
| Assert.cs:16:16:16:32 | String s = ... | null | Assert.cs:16:16:16:16 | access to local variable s | null |
|
||||
| Assert.cs:16:20:16:32 | ... ? ... : ... | non-null | Assert.cs:16:20:16:20 | access to parameter b | false |
|
||||
| Assert.cs:16:20:16:32 | ... ? ... : ... | non-null | Assert.cs:16:31:16:32 | "" | non-null |
|
||||
| Assert.cs:16:20:16:32 | ... ? ... : ... | null | Assert.cs:16:20:16:20 | access to parameter b | true |
|
||||
| Assert.cs:16:20:16:32 | ... ? ... : ... | null | Assert.cs:16:24:16:27 | null | null |
|
||||
| Assert.cs:17:23:17:23 | access to local variable s | empty | Assert.cs:16:20:16:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:17:23:17:23 | access to local variable s | non-empty | Assert.cs:16:20:16:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:17:23:17:23 | access to local variable s | non-null | Assert.cs:16:20:16:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:17:23:17:23 | access to local variable s | null | Assert.cs:16:20:16:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:18:27:18:27 | access to local variable s | non-null | Assert.cs:16:20:16:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:18:27:18:27 | access to local variable s | null | Assert.cs:16:20:16:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:23:16:23:32 | String s = ... | non-null | Assert.cs:23:16:23:16 | access to local variable s | non-null |
|
||||
| Assert.cs:23:16:23:32 | String s = ... | null | Assert.cs:23:16:23:16 | access to local variable s | null |
|
||||
| Assert.cs:23:20:23:32 | ... ? ... : ... | non-null | Assert.cs:23:20:23:20 | access to parameter b | false |
|
||||
| Assert.cs:23:20:23:32 | ... ? ... : ... | non-null | Assert.cs:23:31:23:32 | "" | non-null |
|
||||
| Assert.cs:23:20:23:32 | ... ? ... : ... | null | Assert.cs:23:20:23:20 | access to parameter b | true |
|
||||
| Assert.cs:23:20:23:32 | ... ? ... : ... | null | Assert.cs:23:24:23:27 | null | null |
|
||||
| Assert.cs:24:26:24:26 | access to local variable s | empty | Assert.cs:23:20:23:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:24:26:24:26 | access to local variable s | non-empty | Assert.cs:23:20:23:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:24:26:24:26 | access to local variable s | non-null | Assert.cs:23:20:23:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:24:26:24:26 | access to local variable s | null | Assert.cs:23:20:23:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:25:27:25:27 | access to local variable s | non-null | Assert.cs:23:20:23:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:25:27:25:27 | access to local variable s | null | Assert.cs:23:20:23:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:30:16:30:32 | String s = ... | non-null | Assert.cs:30:16:30:16 | access to local variable s | non-null |
|
||||
| Assert.cs:30:16:30:32 | String s = ... | null | Assert.cs:30:16:30:16 | access to local variable s | null |
|
||||
| Assert.cs:30:20:30:32 | ... ? ... : ... | non-null | Assert.cs:30:20:30:20 | access to parameter b | false |
|
||||
| Assert.cs:30:20:30:32 | ... ? ... : ... | non-null | Assert.cs:30:31:30:32 | "" | non-null |
|
||||
| Assert.cs:30:20:30:32 | ... ? ... : ... | null | Assert.cs:30:20:30:20 | access to parameter b | true |
|
||||
| Assert.cs:30:20:30:32 | ... ? ... : ... | null | Assert.cs:30:24:30:27 | null | null |
|
||||
| Assert.cs:31:23:31:23 | access to local variable s | empty | Assert.cs:30:20:30:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:31:23:31:23 | access to local variable s | non-empty | Assert.cs:30:20:30:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:31:23:31:23 | access to local variable s | non-null | Assert.cs:30:20:30:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:31:23:31:23 | access to local variable s | null | Assert.cs:30:20:30:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:31:23:31:31 | ... == ... | false | Assert.cs:30:20:30:20 | access to parameter b | false |
|
||||
@@ -46,12 +46,12 @@
|
||||
| Assert.cs:31:23:31:31 | ... == ... | true | Assert.cs:31:23:31:23 | access to local variable s | null |
|
||||
| Assert.cs:32:27:32:27 | access to local variable s | non-null | Assert.cs:30:20:30:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:32:27:32:27 | access to local variable s | null | Assert.cs:30:20:30:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:37:16:37:32 | String s = ... | non-null | Assert.cs:37:16:37:16 | access to local variable s | non-null |
|
||||
| Assert.cs:37:16:37:32 | String s = ... | null | Assert.cs:37:16:37:16 | access to local variable s | null |
|
||||
| Assert.cs:37:20:37:32 | ... ? ... : ... | non-null | Assert.cs:37:20:37:20 | access to parameter b | false |
|
||||
| Assert.cs:37:20:37:32 | ... ? ... : ... | non-null | Assert.cs:37:31:37:32 | "" | non-null |
|
||||
| Assert.cs:37:20:37:32 | ... ? ... : ... | null | Assert.cs:37:20:37:20 | access to parameter b | true |
|
||||
| Assert.cs:37:20:37:32 | ... ? ... : ... | null | Assert.cs:37:24:37:27 | null | null |
|
||||
| Assert.cs:38:23:38:23 | access to local variable s | empty | Assert.cs:37:20:37:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:38:23:38:23 | access to local variable s | non-empty | Assert.cs:37:20:37:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:38:23:38:23 | access to local variable s | non-null | Assert.cs:37:20:37:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:38:23:38:23 | access to local variable s | null | Assert.cs:37:20:37:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:38:23:38:31 | ... != ... | false | Assert.cs:37:20:37:20 | access to parameter b | true |
|
||||
@@ -60,12 +60,12 @@
|
||||
| Assert.cs:38:23:38:31 | ... != ... | true | Assert.cs:38:23:38:23 | access to local variable s | non-null |
|
||||
| Assert.cs:39:27:39:27 | access to local variable s | non-null | Assert.cs:37:20:37:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:39:27:39:27 | access to local variable s | null | Assert.cs:37:20:37:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:44:16:44:32 | String s = ... | non-null | Assert.cs:44:16:44:16 | access to local variable s | non-null |
|
||||
| Assert.cs:44:16:44:32 | String s = ... | null | Assert.cs:44:16:44:16 | access to local variable s | null |
|
||||
| Assert.cs:44:20:44:32 | ... ? ... : ... | non-null | Assert.cs:44:20:44:20 | access to parameter b | false |
|
||||
| Assert.cs:44:20:44:32 | ... ? ... : ... | non-null | Assert.cs:44:31:44:32 | "" | non-null |
|
||||
| Assert.cs:44:20:44:32 | ... ? ... : ... | null | Assert.cs:44:20:44:20 | access to parameter b | true |
|
||||
| Assert.cs:44:20:44:32 | ... ? ... : ... | null | Assert.cs:44:24:44:27 | null | null |
|
||||
| Assert.cs:45:24:45:24 | access to local variable s | empty | Assert.cs:44:20:44:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:45:24:45:24 | access to local variable s | non-empty | Assert.cs:44:20:44:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:45:24:45:24 | access to local variable s | non-null | Assert.cs:44:20:44:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:45:24:45:24 | access to local variable s | null | Assert.cs:44:20:44:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:45:24:45:32 | ... != ... | false | Assert.cs:44:20:44:20 | access to parameter b | true |
|
||||
@@ -74,12 +74,12 @@
|
||||
| Assert.cs:45:24:45:32 | ... != ... | true | Assert.cs:45:24:45:24 | access to local variable s | non-null |
|
||||
| Assert.cs:46:27:46:27 | access to local variable s | non-null | Assert.cs:44:20:44:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:46:27:46:27 | access to local variable s | null | Assert.cs:44:20:44:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:51:16:51:32 | String s = ... | non-null | Assert.cs:51:16:51:16 | access to local variable s | non-null |
|
||||
| Assert.cs:51:16:51:32 | String s = ... | null | Assert.cs:51:16:51:16 | access to local variable s | null |
|
||||
| Assert.cs:51:20:51:32 | ... ? ... : ... | non-null | Assert.cs:51:20:51:20 | access to parameter b | false |
|
||||
| Assert.cs:51:20:51:32 | ... ? ... : ... | non-null | Assert.cs:51:31:51:32 | "" | non-null |
|
||||
| Assert.cs:51:20:51:32 | ... ? ... : ... | null | Assert.cs:51:20:51:20 | access to parameter b | true |
|
||||
| Assert.cs:51:20:51:32 | ... ? ... : ... | null | Assert.cs:51:24:51:27 | null | null |
|
||||
| Assert.cs:52:24:52:24 | access to local variable s | empty | Assert.cs:51:20:51:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:52:24:52:24 | access to local variable s | non-empty | Assert.cs:51:20:51:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:52:24:52:24 | access to local variable s | non-null | Assert.cs:51:20:51:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:52:24:52:24 | access to local variable s | null | Assert.cs:51:20:51:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:52:24:52:32 | ... == ... | false | Assert.cs:51:20:51:20 | access to parameter b | false |
|
||||
@@ -88,12 +88,12 @@
|
||||
| Assert.cs:52:24:52:32 | ... == ... | true | Assert.cs:52:24:52:24 | access to local variable s | null |
|
||||
| Assert.cs:53:27:53:27 | access to local variable s | non-null | Assert.cs:51:20:51:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:53:27:53:27 | access to local variable s | null | Assert.cs:51:20:51:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:58:16:58:32 | String s = ... | non-null | Assert.cs:58:16:58:16 | access to local variable s | non-null |
|
||||
| Assert.cs:58:16:58:32 | String s = ... | null | Assert.cs:58:16:58:16 | access to local variable s | null |
|
||||
| Assert.cs:58:20:58:32 | ... ? ... : ... | non-null | Assert.cs:58:20:58:20 | access to parameter b | false |
|
||||
| Assert.cs:58:20:58:32 | ... ? ... : ... | non-null | Assert.cs:58:31:58:32 | "" | non-null |
|
||||
| Assert.cs:58:20:58:32 | ... ? ... : ... | null | Assert.cs:58:20:58:20 | access to parameter b | true |
|
||||
| Assert.cs:58:20:58:32 | ... ? ... : ... | null | Assert.cs:58:24:58:27 | null | null |
|
||||
| Assert.cs:59:23:59:23 | access to local variable s | empty | Assert.cs:58:20:58:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:59:23:59:23 | access to local variable s | non-empty | Assert.cs:58:20:58:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:59:23:59:23 | access to local variable s | non-null | Assert.cs:58:20:58:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:59:23:59:23 | access to local variable s | null | Assert.cs:58:20:58:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:59:23:59:31 | ... != ... | false | Assert.cs:58:20:58:20 | access to parameter b | true |
|
||||
@@ -104,12 +104,12 @@
|
||||
| Assert.cs:59:23:59:36 | ... && ... | true | Assert.cs:59:36:59:36 | access to parameter b | true |
|
||||
| Assert.cs:60:27:60:27 | access to local variable s | non-null | Assert.cs:58:20:58:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:60:27:60:27 | access to local variable s | null | Assert.cs:58:20:58:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:65:16:65:32 | String s = ... | non-null | Assert.cs:65:16:65:16 | access to local variable s | non-null |
|
||||
| Assert.cs:65:16:65:32 | String s = ... | null | Assert.cs:65:16:65:16 | access to local variable s | null |
|
||||
| Assert.cs:65:20:65:32 | ... ? ... : ... | non-null | Assert.cs:65:20:65:20 | access to parameter b | false |
|
||||
| Assert.cs:65:20:65:32 | ... ? ... : ... | non-null | Assert.cs:65:31:65:32 | "" | non-null |
|
||||
| Assert.cs:65:20:65:32 | ... ? ... : ... | null | Assert.cs:65:20:65:20 | access to parameter b | true |
|
||||
| Assert.cs:65:20:65:32 | ... ? ... : ... | null | Assert.cs:65:24:65:27 | null | null |
|
||||
| Assert.cs:66:24:66:24 | access to local variable s | empty | Assert.cs:65:20:65:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:66:24:66:24 | access to local variable s | non-empty | Assert.cs:65:20:65:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:66:24:66:24 | access to local variable s | non-null | Assert.cs:65:20:65:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:66:24:66:24 | access to local variable s | null | Assert.cs:65:20:65:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:66:24:66:32 | ... == ... | false | Assert.cs:65:20:65:20 | access to parameter b | false |
|
||||
@@ -120,12 +120,12 @@
|
||||
| Assert.cs:66:24:66:37 | ... \|\| ... | false | Assert.cs:66:37:66:37 | access to parameter b | false |
|
||||
| Assert.cs:67:27:67:27 | access to local variable s | non-null | Assert.cs:65:20:65:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:67:27:67:27 | access to local variable s | null | Assert.cs:65:20:65:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:72:16:72:32 | String s = ... | non-null | Assert.cs:72:16:72:16 | access to local variable s | non-null |
|
||||
| Assert.cs:72:16:72:32 | String s = ... | null | Assert.cs:72:16:72:16 | access to local variable s | null |
|
||||
| Assert.cs:72:20:72:32 | ... ? ... : ... | non-null | Assert.cs:72:20:72:20 | access to parameter b | false |
|
||||
| Assert.cs:72:20:72:32 | ... ? ... : ... | non-null | Assert.cs:72:31:72:32 | "" | non-null |
|
||||
| Assert.cs:72:20:72:32 | ... ? ... : ... | null | Assert.cs:72:20:72:20 | access to parameter b | true |
|
||||
| Assert.cs:72:20:72:32 | ... ? ... : ... | null | Assert.cs:72:24:72:27 | null | null |
|
||||
| Assert.cs:73:23:73:23 | access to local variable s | empty | Assert.cs:72:20:72:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:73:23:73:23 | access to local variable s | non-empty | Assert.cs:72:20:72:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:73:23:73:23 | access to local variable s | non-null | Assert.cs:72:20:72:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:73:23:73:23 | access to local variable s | null | Assert.cs:72:20:72:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:73:23:73:31 | ... == ... | false | Assert.cs:72:20:72:20 | access to parameter b | false |
|
||||
@@ -136,12 +136,12 @@
|
||||
| Assert.cs:73:23:73:36 | ... && ... | true | Assert.cs:73:36:73:36 | access to parameter b | true |
|
||||
| Assert.cs:74:27:74:27 | access to local variable s | non-null | Assert.cs:72:20:72:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:74:27:74:27 | access to local variable s | null | Assert.cs:72:20:72:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:79:16:79:32 | String s = ... | non-null | Assert.cs:79:16:79:16 | access to local variable s | non-null |
|
||||
| Assert.cs:79:16:79:32 | String s = ... | null | Assert.cs:79:16:79:16 | access to local variable s | null |
|
||||
| Assert.cs:79:20:79:32 | ... ? ... : ... | non-null | Assert.cs:79:20:79:20 | access to parameter b | false |
|
||||
| Assert.cs:79:20:79:32 | ... ? ... : ... | non-null | Assert.cs:79:31:79:32 | "" | non-null |
|
||||
| Assert.cs:79:20:79:32 | ... ? ... : ... | null | Assert.cs:79:20:79:20 | access to parameter b | true |
|
||||
| Assert.cs:79:20:79:32 | ... ? ... : ... | null | Assert.cs:79:24:79:27 | null | null |
|
||||
| Assert.cs:80:24:80:24 | access to local variable s | empty | Assert.cs:79:20:79:32 | ... ? ... : ... | empty |
|
||||
| Assert.cs:80:24:80:24 | access to local variable s | non-empty | Assert.cs:79:20:79:32 | ... ? ... : ... | non-empty |
|
||||
| Assert.cs:80:24:80:24 | access to local variable s | non-null | Assert.cs:79:20:79:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:80:24:80:24 | access to local variable s | null | Assert.cs:79:20:79:32 | ... ? ... : ... | null |
|
||||
| Assert.cs:80:24:80:32 | ... != ... | false | Assert.cs:79:20:79:20 | access to parameter b | true |
|
||||
@@ -152,6 +152,62 @@
|
||||
| Assert.cs:80:24:80:37 | ... \|\| ... | false | Assert.cs:80:37:80:37 | access to parameter b | false |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | non-null | Assert.cs:79:20:79:32 | ... ? ... : ... | non-null |
|
||||
| Assert.cs:81:27:81:27 | access to local variable s | null | Assert.cs:79:20:79:32 | ... ? ... : ... | null |
|
||||
| Collections.cs:12:17:12:32 | ... == ... | false | Collections.cs:12:17:12:20 | access to parameter args | non-empty |
|
||||
| Collections.cs:12:17:12:32 | ... == ... | true | Collections.cs:12:17:12:20 | access to parameter args | empty |
|
||||
| Collections.cs:13:13:13:28 | ... == ... | true | Collections.cs:13:13:13:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:14:13:14:28 | ... != ... | false | Collections.cs:14:13:14:16 | access to parameter args | empty |
|
||||
| Collections.cs:14:13:14:28 | ... != ... | true | Collections.cs:14:13:14:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:15:13:15:28 | ... != ... | false | Collections.cs:15:13:15:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:16:13:16:27 | ... > ... | true | Collections.cs:16:13:16:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:18:13:18:28 | ... >= ... | true | Collections.cs:18:13:18:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:23:17:23:31 | ... == ... | false | Collections.cs:23:17:23:20 | access to parameter args | non-empty |
|
||||
| Collections.cs:23:17:23:31 | ... == ... | true | Collections.cs:23:17:23:20 | access to parameter args | empty |
|
||||
| Collections.cs:24:13:24:27 | ... == ... | true | Collections.cs:24:13:24:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:25:13:25:27 | ... != ... | false | Collections.cs:25:13:25:16 | access to parameter args | empty |
|
||||
| Collections.cs:25:13:25:27 | ... != ... | true | Collections.cs:25:13:25:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:26:13:26:27 | ... != ... | false | Collections.cs:26:13:26:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:27:13:27:26 | ... > ... | true | Collections.cs:27:13:27:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:29:13:29:27 | ... >= ... | true | Collections.cs:29:13:29:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:34:17:34:33 | ... == ... | false | Collections.cs:34:17:34:20 | access to parameter args | non-empty |
|
||||
| Collections.cs:34:17:34:33 | ... == ... | true | Collections.cs:34:17:34:20 | access to parameter args | empty |
|
||||
| Collections.cs:35:13:35:29 | ... == ... | true | Collections.cs:35:13:35:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:36:13:36:29 | ... != ... | false | Collections.cs:36:13:36:16 | access to parameter args | empty |
|
||||
| Collections.cs:36:13:36:29 | ... != ... | true | Collections.cs:36:13:36:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:37:13:37:29 | ... != ... | false | Collections.cs:37:13:37:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:38:13:38:28 | ... > ... | true | Collections.cs:38:13:38:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:40:13:40:29 | ... >= ... | true | Collections.cs:40:13:40:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:45:17:45:26 | call to method Any | false | Collections.cs:45:17:45:20 | access to parameter args | empty |
|
||||
| Collections.cs:45:17:45:26 | call to method Any | true | Collections.cs:45:17:45:20 | access to parameter args | non-empty |
|
||||
| Collections.cs:50:13:50:27 | ... == ... | false | Collections.cs:50:13:50:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:50:13:50:27 | ... == ... | true | Collections.cs:50:13:50:16 | access to parameter args | empty |
|
||||
| Collections.cs:56:13:56:13 | access to local variable x | empty | Collections.cs:55:13:55:41 | array creation of type String[] | empty |
|
||||
| Collections.cs:56:13:56:13 | access to local variable x | non-empty | Collections.cs:55:13:55:41 | array creation of type String[] | non-empty |
|
||||
| Collections.cs:56:13:56:13 | access to local variable x | non-null | Collections.cs:55:13:55:41 | array creation of type String[] | non-null |
|
||||
| Collections.cs:56:13:56:13 | access to local variable x | null | Collections.cs:55:13:55:41 | array creation of type String[] | null |
|
||||
| Collections.cs:58:13:58:13 | access to local variable x | empty | Collections.cs:57:13:57:25 | array creation of type String[] | empty |
|
||||
| Collections.cs:58:13:58:13 | access to local variable x | non-empty | Collections.cs:57:13:57:25 | array creation of type String[] | non-empty |
|
||||
| Collections.cs:58:13:58:13 | access to local variable x | non-null | Collections.cs:57:13:57:25 | array creation of type String[] | non-null |
|
||||
| Collections.cs:58:13:58:13 | access to local variable x | null | Collections.cs:57:13:57:25 | array creation of type String[] | null |
|
||||
| Collections.cs:64:9:64:9 | access to local variable x | empty | Collections.cs:63:17:63:54 | call to method ToList | empty |
|
||||
| Collections.cs:64:9:64:9 | access to local variable x | non-empty | Collections.cs:63:17:63:54 | call to method ToList | non-empty |
|
||||
| Collections.cs:64:9:64:9 | access to local variable x | non-null | Collections.cs:63:17:63:54 | call to method ToList | non-null |
|
||||
| Collections.cs:64:9:64:9 | access to local variable x | null | Collections.cs:63:17:63:54 | call to method ToList | null |
|
||||
| Collections.cs:65:13:65:13 | access to local variable x | non-null | Collections.cs:63:17:63:54 | call to method ToList | non-null |
|
||||
| Collections.cs:65:13:65:13 | access to local variable x | null | Collections.cs:63:17:63:54 | call to method ToList | null |
|
||||
| Collections.cs:65:13:65:24 | ... == ... | false | Collections.cs:65:13:65:13 | access to local variable x | non-empty |
|
||||
| Collections.cs:65:13:65:24 | ... == ... | true | Collections.cs:65:13:65:13 | access to local variable x | empty |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | non-null | Collections.cs:63:17:63:54 | call to method ToList | non-null |
|
||||
| Collections.cs:67:13:67:13 | access to local variable x | null | Collections.cs:63:17:63:54 | call to method ToList | null |
|
||||
| Collections.cs:68:13:68:13 | access to local variable x | non-null | Collections.cs:63:17:63:54 | call to method ToList | non-null |
|
||||
| Collections.cs:68:13:68:13 | access to local variable x | null | Collections.cs:63:17:63:54 | call to method ToList | null |
|
||||
| Collections.cs:74:35:74:41 | ... == ... | true | Collections.cs:74:35:74:35 | access to parameter s | non-null |
|
||||
| Collections.cs:75:17:75:33 | call to method Any | true | Collections.cs:75:17:75:20 | access to parameter args | non-empty |
|
||||
| Collections.cs:76:13:76:36 | ... == ... | false | Collections.cs:76:13:76:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:77:13:77:36 | ... == ... | true | Collections.cs:77:13:77:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:78:13:78:36 | ... != ... | true | Collections.cs:78:13:78:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:79:13:79:36 | ... != ... | false | Collections.cs:79:13:79:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:80:13:80:35 | ... > ... | true | Collections.cs:80:13:80:16 | access to parameter args | non-empty |
|
||||
| Collections.cs:82:13:82:36 | ... >= ... | true | Collections.cs:82:13:82:16 | access to parameter args | non-empty |
|
||||
| Guards.cs:10:13:10:25 | !... | false | Guards.cs:10:14:10:25 | !... | true |
|
||||
| Guards.cs:10:13:10:25 | !... | true | Guards.cs:10:14:10:25 | !... | false |
|
||||
| Guards.cs:10:14:10:25 | !... | false | Guards.cs:10:16:10:24 | ... == ... | true |
|
||||
@@ -213,10 +269,8 @@
|
||||
| Guards.cs:60:13:60:45 | ... == ... | true | Guards.cs:60:13:60:37 | access to field Field | null |
|
||||
| Guards.cs:68:16:68:24 | ... != ... | false | Guards.cs:68:16:68:16 | access to parameter s | null |
|
||||
| Guards.cs:68:16:68:24 | ... != ... | true | Guards.cs:68:16:68:16 | access to parameter s | non-null |
|
||||
| Guards.cs:71:13:71:20 | ... = ... | non-null | Guards.cs:71:13:71:13 | access to parameter s | non-null |
|
||||
| Guards.cs:71:13:71:20 | ... = ... | non-null | Guards.cs:71:17:71:20 | null | non-null |
|
||||
| Guards.cs:71:13:71:20 | ... = ... | null | Guards.cs:71:13:71:13 | access to parameter s | null |
|
||||
| Guards.cs:71:13:71:20 | ... = ... | null | Guards.cs:71:17:71:20 | null | null |
|
||||
| Guards.cs:72:31:72:31 | access to parameter s | empty | Guards.cs:71:17:71:20 | null | empty |
|
||||
| Guards.cs:72:31:72:31 | access to parameter s | non-empty | Guards.cs:71:17:71:20 | null | non-empty |
|
||||
| Guards.cs:72:31:72:31 | access to parameter s | non-null | Guards.cs:71:17:71:20 | null | non-null |
|
||||
| Guards.cs:72:31:72:31 | access to parameter s | null | Guards.cs:71:17:71:20 | null | null |
|
||||
| Guards.cs:78:13:78:26 | ... == ... | true | Guards.cs:78:15:78:21 | access to property Length | non-null |
|
||||
@@ -247,36 +301,18 @@
|
||||
| Guards.cs:96:13:96:19 | ... == ... | true | Guards.cs:96:13:96:13 | access to parameter s | non-null |
|
||||
| Guards.cs:104:13:104:45 | ... == ... | false | Guards.cs:104:13:104:37 | access to field Field | non-null |
|
||||
| Guards.cs:104:13:104:45 | ... == ... | true | Guards.cs:104:13:104:37 | access to field Field | null |
|
||||
| Guards.cs:106:9:106:25 | ... = ... | non-null | Guards.cs:106:9:106:18 | access to property Property | non-null |
|
||||
| Guards.cs:106:9:106:25 | ... = ... | non-null | Guards.cs:106:22:106:25 | null | non-null |
|
||||
| Guards.cs:106:9:106:25 | ... = ... | null | Guards.cs:106:9:106:18 | access to property Property | null |
|
||||
| Guards.cs:106:9:106:25 | ... = ... | null | Guards.cs:106:22:106:25 | null | null |
|
||||
| Guards.cs:107:27:107:36 | access to property Property | non-null | Guards.cs:106:22:106:25 | null | non-null |
|
||||
| Guards.cs:107:27:107:36 | access to property Property | null | Guards.cs:106:22:106:25 | null | null |
|
||||
| Guards.cs:108:27:108:36 | access to property Property | non-null | Guards.cs:106:22:106:25 | null | non-null |
|
||||
| Guards.cs:108:27:108:36 | access to property Property | null | Guards.cs:106:22:106:25 | null | null |
|
||||
| Guards.cs:113:13:114:38 | String dummy = ... | non-null | Guards.cs:113:13:113:17 | access to local variable dummy | non-null |
|
||||
| Guards.cs:113:13:114:38 | String dummy = ... | null | Guards.cs:113:13:113:17 | access to local variable dummy | null |
|
||||
| Guards.cs:113:21:114:38 | ... ?? ... | null | Guards.cs:113:21:113:45 | access to field Field | null |
|
||||
| Guards.cs:113:21:114:38 | ... ?? ... | null | Guards.cs:114:14:114:38 | access to field Field | null |
|
||||
| Guards.cs:115:9:115:55 | ... = ... | non-null | Guards.cs:115:9:115:13 | access to local variable dummy | non-null |
|
||||
| Guards.cs:115:9:115:55 | ... = ... | non-null | Guards.cs:115:17:115:55 | ... ?? ... | non-null |
|
||||
| Guards.cs:115:9:115:55 | ... = ... | null | Guards.cs:115:9:115:13 | access to local variable dummy | null |
|
||||
| Guards.cs:115:9:115:55 | ... = ... | null | Guards.cs:115:17:115:55 | ... ?? ... | null |
|
||||
| Guards.cs:115:17:115:55 | ... ?? ... | null | Guards.cs:115:17:115:41 | access to field Field | null |
|
||||
| Guards.cs:115:17:115:55 | ... ?? ... | null | Guards.cs:115:46:115:55 | throw ... | null |
|
||||
| Guards.cs:117:9:117:25 | ... = ... | non-null | Guards.cs:117:9:117:18 | access to property Property | non-null |
|
||||
| Guards.cs:117:9:117:25 | ... = ... | non-null | Guards.cs:117:22:117:25 | null | non-null |
|
||||
| Guards.cs:117:9:117:25 | ... = ... | null | Guards.cs:117:9:117:18 | access to property Property | null |
|
||||
| Guards.cs:117:9:117:25 | ... = ... | null | Guards.cs:117:22:117:25 | null | null |
|
||||
| Guards.cs:118:27:118:36 | access to property Property | non-null | Guards.cs:117:22:117:25 | null | non-null |
|
||||
| Guards.cs:118:27:118:36 | access to property Property | null | Guards.cs:117:22:117:25 | null | null |
|
||||
| Guards.cs:119:27:119:36 | access to property Property | non-null | Guards.cs:117:22:117:25 | null | non-null |
|
||||
| Guards.cs:119:27:119:36 | access to property Property | null | Guards.cs:117:22:117:25 | null | null |
|
||||
| Guards.cs:124:13:124:30 | Boolean b1 = ... | false | Guards.cs:124:13:124:14 | access to local variable b1 | false |
|
||||
| Guards.cs:124:13:124:30 | Boolean b1 = ... | true | Guards.cs:124:13:124:14 | access to local variable b1 | true |
|
||||
| Guards.cs:125:13:125:31 | Nullable<Boolean> b2 = ... | non-null | Guards.cs:125:13:125:14 | access to local variable b2 | non-null |
|
||||
| Guards.cs:125:13:125:31 | Nullable<Boolean> b2 = ... | null | Guards.cs:125:13:125:14 | access to local variable b2 | null |
|
||||
| Guards.cs:125:21:125:31 | call to method Equals | non-null | Guards.cs:125:18:125:19 | access to parameter s1 | non-null |
|
||||
| Guards.cs:125:21:125:31 | call to method Equals | null | Guards.cs:125:18:125:19 | access to parameter s1 | null |
|
||||
| Guards.cs:130:13:130:21 | ... is ... | false | Guards.cs:130:13:130:13 | access to parameter s | non-null |
|
||||
@@ -284,6 +320,8 @@
|
||||
| Guards.cs:137:13:137:25 | ... is ... | false | Guards.cs:137:13:137:13 | access to parameter s | null |
|
||||
| Guards.cs:137:13:137:25 | ... is ... | true | Guards.cs:137:13:137:13 | access to parameter s | non-null |
|
||||
| Guards.cs:144:13:144:25 | ... is ... | true | Guards.cs:144:13:144:13 | access to parameter o | non-null |
|
||||
| Guards.cs:145:20:145:20 | access to local variable s | empty | Guards.cs:144:13:144:13 | access to parameter o | empty |
|
||||
| Guards.cs:145:20:145:20 | access to local variable s | non-empty | Guards.cs:144:13:144:13 | access to parameter o | non-empty |
|
||||
| Guards.cs:145:20:145:20 | access to local variable s | non-null | Guards.cs:144:13:144:13 | access to parameter o | non-null |
|
||||
| Guards.cs:145:20:145:20 | access to local variable s | null | Guards.cs:144:13:144:13 | access to parameter o | null |
|
||||
| Guards.cs:151:17:151:17 | access to parameter o | match "" | Guards.cs:151:17:151:17 | access to parameter o | non-null |
|
||||
@@ -330,16 +368,8 @@
|
||||
| Guards.cs:197:13:197:29 | !... | true | Guards.cs:197:14:197:29 | call to method NullTestWrong | false |
|
||||
| Guards.cs:203:13:203:21 | ... != ... | false | Guards.cs:203:13:203:13 | access to parameter o | null |
|
||||
| Guards.cs:203:13:203:21 | ... != ... | true | Guards.cs:203:13:203:13 | access to parameter o | non-null |
|
||||
| Guards.cs:215:13:215:21 | Boolean b2 = ... | false | Guards.cs:215:13:215:14 | access to local variable b2 | false |
|
||||
| Guards.cs:215:13:215:21 | Boolean b2 = ... | true | Guards.cs:215:13:215:14 | access to local variable b2 | true |
|
||||
| Guards.cs:217:13:217:22 | ... = ... | false | Guards.cs:217:13:217:14 | access to local variable b2 | false |
|
||||
| Guards.cs:217:13:217:22 | ... = ... | true | Guards.cs:217:13:217:14 | access to local variable b2 | true |
|
||||
| Guards.cs:218:17:218:18 | access to local variable b2 | match true | Guards.cs:216:13:216:14 | access to parameter b1 | false |
|
||||
| Guards.cs:218:17:218:18 | access to local variable b2 | match true | Guards.cs:218:17:218:18 | access to local variable b2 | true |
|
||||
| Guards.cs:228:13:228:22 | Boolean b2 = ... | false | Guards.cs:228:13:228:14 | access to local variable b2 | false |
|
||||
| Guards.cs:228:13:228:22 | Boolean b2 = ... | true | Guards.cs:228:13:228:14 | access to local variable b2 | true |
|
||||
| Guards.cs:230:13:230:21 | ... = ... | false | Guards.cs:230:13:230:14 | access to local variable b2 | false |
|
||||
| Guards.cs:230:13:230:21 | ... = ... | true | Guards.cs:230:13:230:14 | access to local variable b2 | true |
|
||||
| Guards.cs:231:17:231:18 | access to local variable b2 | match true | Guards.cs:229:13:229:14 | access to parameter b1 | true |
|
||||
| Guards.cs:231:17:231:18 | access to local variable b2 | match true | Guards.cs:231:17:231:18 | access to local variable b2 | true |
|
||||
| Guards.cs:231:17:231:18 | access to local variable b2 | non-match true | Guards.cs:229:13:229:14 | access to parameter b1 | false |
|
||||
@@ -360,16 +390,8 @@
|
||||
| Guards.cs:276:16:276:16 | access to parameter o | non-match null | Guards.cs:276:16:276:16 | access to parameter o | non-null |
|
||||
| Guards.cs:281:17:281:17 | access to local variable a | non-null | Guards.cs:276:16:276:16 | access to parameter o | non-null |
|
||||
| Guards.cs:281:17:281:17 | access to local variable a | null | Guards.cs:276:16:276:16 | access to parameter o | null |
|
||||
| Guards.cs:293:13:293:21 | Boolean b2 = ... | false | Guards.cs:293:13:293:14 | access to local variable b2 | false |
|
||||
| Guards.cs:293:13:293:21 | Boolean b2 = ... | true | Guards.cs:293:13:293:14 | access to local variable b2 | true |
|
||||
| Guards.cs:295:13:295:22 | ... = ... | false | Guards.cs:295:13:295:14 | access to local variable b2 | false |
|
||||
| Guards.cs:295:13:295:22 | ... = ... | true | Guards.cs:295:13:295:14 | access to local variable b2 | true |
|
||||
| Guards.cs:296:16:296:17 | access to local variable b2 | match true | Guards.cs:294:13:294:14 | access to parameter b1 | false |
|
||||
| Guards.cs:296:16:296:17 | access to local variable b2 | match true | Guards.cs:296:16:296:17 | access to local variable b2 | true |
|
||||
| Guards.cs:305:13:305:22 | Boolean b2 = ... | false | Guards.cs:305:13:305:14 | access to local variable b2 | false |
|
||||
| Guards.cs:305:13:305:22 | Boolean b2 = ... | true | Guards.cs:305:13:305:14 | access to local variable b2 | true |
|
||||
| Guards.cs:307:13:307:21 | ... = ... | false | Guards.cs:307:13:307:14 | access to local variable b2 | false |
|
||||
| Guards.cs:307:13:307:21 | ... = ... | true | Guards.cs:307:13:307:14 | access to local variable b2 | true |
|
||||
| Guards.cs:308:16:308:17 | access to local variable b2 | match true | Guards.cs:306:13:306:14 | access to parameter b1 | true |
|
||||
| Guards.cs:308:16:308:17 | access to local variable b2 | match true | Guards.cs:308:16:308:17 | access to local variable b2 | true |
|
||||
| Guards.cs:308:16:308:17 | access to local variable b2 | non-match true | Guards.cs:306:13:306:14 | access to parameter b1 | false |
|
||||
@@ -401,13 +423,7 @@
|
||||
| Splitting.cs:105:22:105:30 | ... != ... | true | Splitting.cs:105:22:105:22 | access to parameter o | non-null |
|
||||
| Splitting.cs:116:22:116:30 | ... != ... | false | Splitting.cs:116:22:116:22 | access to parameter o | null |
|
||||
| Splitting.cs:116:22:116:30 | ... != ... | true | Splitting.cs:116:22:116:22 | access to parameter o | non-null |
|
||||
| Splitting.cs:125:16:125:23 | Object o = ... | non-null | Splitting.cs:125:16:125:16 | access to local variable o | non-null |
|
||||
| Splitting.cs:125:16:125:23 | Object o = ... | null | Splitting.cs:125:16:125:16 | access to local variable o | null |
|
||||
| Splitting.cs:128:17:128:25 | ... != ... | false | Splitting.cs:128:17:128:17 | access to local variable o | null |
|
||||
| Splitting.cs:128:17:128:25 | ... != ... | true | Splitting.cs:128:17:128:17 | access to local variable o | non-null |
|
||||
| Splitting.cs:132:17:132:29 | ... = ... | non-null | Splitting.cs:132:17:132:17 | access to local variable o | non-null |
|
||||
| Splitting.cs:132:17:132:29 | ... = ... | non-null | Splitting.cs:132:21:132:29 | call to method M11 | non-null |
|
||||
| Splitting.cs:132:17:132:29 | ... = ... | null | Splitting.cs:132:17:132:17 | access to local variable o | null |
|
||||
| Splitting.cs:132:17:132:29 | ... = ... | null | Splitting.cs:132:21:132:29 | call to method M11 | null |
|
||||
| Splitting.cs:133:17:133:17 | access to local variable o | non-null | Splitting.cs:132:21:132:29 | call to method M11 | non-null |
|
||||
| Splitting.cs:133:17:133:17 | access to local variable o | null | Splitting.cs:132:21:132:29 | call to method M11 | null |
|
||||
|
||||
@@ -173,6 +173,204 @@ edges
|
||||
| G.cs:52:14:52:21 | access to field boxfield [Box1, Elem] | G.cs:52:14:52:26 | access to field Box1 [Elem] |
|
||||
| G.cs:52:14:52:21 | this access [boxfield, Box1, ... (3)] | G.cs:52:14:52:21 | access to field boxfield [Box1, Elem] |
|
||||
| G.cs:52:14:52:26 | access to field Box1 [Elem] | G.cs:52:14:52:31 | access to field Elem |
|
||||
nodes
|
||||
| A.cs:5:17:5:23 | object creation of type C | semmle.label | object creation of type C |
|
||||
| A.cs:6:17:6:25 | call to method Make [c] | semmle.label | call to method Make [c] |
|
||||
| A.cs:6:24:6:24 | access to local variable c | semmle.label | access to local variable c |
|
||||
| A.cs:7:14:7:14 | access to local variable b [c] | semmle.label | access to local variable b [c] |
|
||||
| A.cs:7:14:7:16 | access to field c | semmle.label | access to field c |
|
||||
| A.cs:13:9:13:9 | [post] access to local variable b [c] | semmle.label | [post] access to local variable b [c] |
|
||||
| A.cs:13:15:13:22 | object creation of type C1 | semmle.label | object creation of type C1 |
|
||||
| A.cs:14:14:14:14 | access to local variable b [c] | semmle.label | access to local variable b [c] |
|
||||
| A.cs:14:14:14:20 | call to method Get | semmle.label | call to method Get |
|
||||
| A.cs:15:14:15:35 | call to method Get | semmle.label | call to method Get |
|
||||
| A.cs:15:15:15:28 | object creation of type B [c] | semmle.label | object creation of type B [c] |
|
||||
| A.cs:15:21:15:27 | object creation of type C | semmle.label | object creation of type C |
|
||||
| A.cs:22:14:22:33 | call to method SetOnB [c] | semmle.label | call to method SetOnB [c] |
|
||||
| A.cs:22:25:22:32 | object creation of type C2 | semmle.label | object creation of type C2 |
|
||||
| A.cs:24:14:24:15 | access to local variable b2 [c] | semmle.label | access to local variable b2 [c] |
|
||||
| A.cs:24:14:24:17 | access to field c | semmle.label | access to field c |
|
||||
| A.cs:31:14:31:37 | call to method SetOnBWrap [c] | semmle.label | call to method SetOnBWrap [c] |
|
||||
| A.cs:31:29:31:36 | object creation of type C2 | semmle.label | object creation of type C2 |
|
||||
| A.cs:33:14:33:15 | access to local variable b2 [c] | semmle.label | access to local variable b2 [c] |
|
||||
| A.cs:33:14:33:17 | access to field c | semmle.label | access to field c |
|
||||
| A.cs:55:17:55:23 | object creation of type A | semmle.label | object creation of type A |
|
||||
| A.cs:57:9:57:10 | [post] access to local variable c1 [a] | semmle.label | [post] access to local variable c1 [a] |
|
||||
| A.cs:57:16:57:16 | access to local variable a | semmle.label | access to local variable a |
|
||||
| A.cs:58:12:58:13 | access to local variable c1 [a] | semmle.label | access to local variable c1 [a] |
|
||||
| A.cs:60:22:60:22 | c [a] | semmle.label | c [a] |
|
||||
| A.cs:64:18:64:26 | access to field a | semmle.label | access to field a |
|
||||
| A.cs:64:19:64:23 | (...) ... [a] | semmle.label | (...) ... [a] |
|
||||
| A.cs:69:18:69:22 | (...) ... [a] | semmle.label | (...) ... [a] |
|
||||
| A.cs:77:18:77:27 | access to field a | semmle.label | access to field a |
|
||||
| A.cs:77:19:77:24 | (...) ... [a] | semmle.label | (...) ... [a] |
|
||||
| A.cs:83:9:83:9 | [post] access to parameter b [c] | semmle.label | [post] access to parameter b [c] |
|
||||
| A.cs:83:15:83:21 | object creation of type C | semmle.label | object creation of type C |
|
||||
| A.cs:88:12:88:12 | [post] access to local variable b [c] | semmle.label | [post] access to local variable b [c] |
|
||||
| A.cs:89:14:89:14 | access to local variable b [c] | semmle.label | access to local variable b [c] |
|
||||
| A.cs:89:14:89:16 | access to field c | semmle.label | access to field c |
|
||||
| A.cs:97:13:97:13 | [post] access to parameter b [c] | semmle.label | [post] access to parameter b [c] |
|
||||
| A.cs:97:19:97:25 | object creation of type C | semmle.label | object creation of type C |
|
||||
| A.cs:98:13:98:16 | [post] this access [b, c] | semmle.label | [post] this access [b, c] |
|
||||
| A.cs:98:13:98:16 | [post] this access [b] | semmle.label | [post] this access [b] |
|
||||
| A.cs:98:22:98:36 | ... ? ... : ... | semmle.label | ... ? ... : ... |
|
||||
| A.cs:98:22:98:36 | ... ? ... : ... [c] | semmle.label | ... ? ... : ... [c] |
|
||||
| A.cs:98:30:98:36 | object creation of type B | semmle.label | object creation of type B |
|
||||
| A.cs:104:17:104:23 | object creation of type B | semmle.label | object creation of type B |
|
||||
| A.cs:105:17:105:29 | object creation of type D [b, c] | semmle.label | object creation of type D [b, c] |
|
||||
| A.cs:105:17:105:29 | object creation of type D [b] | semmle.label | object creation of type D [b] |
|
||||
| A.cs:105:23:105:23 | [post] access to local variable b [c] | semmle.label | [post] access to local variable b [c] |
|
||||
| A.cs:105:23:105:23 | access to local variable b | semmle.label | access to local variable b |
|
||||
| A.cs:106:14:106:14 | access to local variable d [b] | semmle.label | access to local variable d [b] |
|
||||
| A.cs:106:14:106:16 | access to field b | semmle.label | access to field b |
|
||||
| A.cs:107:14:107:14 | access to local variable d [b, c] | semmle.label | access to local variable d [b, c] |
|
||||
| A.cs:107:14:107:16 | access to field b [c] | semmle.label | access to field b [c] |
|
||||
| A.cs:107:14:107:18 | access to field c | semmle.label | access to field c |
|
||||
| A.cs:108:14:108:14 | access to local variable b [c] | semmle.label | access to local variable b [c] |
|
||||
| A.cs:108:14:108:16 | access to field c | semmle.label | access to field c |
|
||||
| A.cs:113:17:113:23 | object creation of type B | semmle.label | object creation of type B |
|
||||
| A.cs:114:18:114:54 | object creation of type MyList [head] | semmle.label | object creation of type MyList [head] |
|
||||
| A.cs:114:29:114:29 | access to local variable b | semmle.label | access to local variable b |
|
||||
| A.cs:115:18:115:37 | object creation of type MyList [next, head] | semmle.label | object creation of type MyList [next, head] |
|
||||
| A.cs:115:35:115:36 | access to local variable l1 [head] | semmle.label | access to local variable l1 [head] |
|
||||
| A.cs:116:18:116:37 | object creation of type MyList [next, next, ... (3)] | semmle.label | object creation of type MyList [next, next, ... (3)] |
|
||||
| A.cs:116:35:116:36 | access to local variable l2 [next, head] | semmle.label | access to local variable l2 [next, head] |
|
||||
| A.cs:119:14:119:15 | access to local variable l3 [next, next, ... (3)] | semmle.label | access to local variable l3 [next, next, ... (3)] |
|
||||
| A.cs:119:14:119:20 | access to field next [next, head] | semmle.label | access to field next [next, head] |
|
||||
| A.cs:119:14:119:25 | access to field next [head] | semmle.label | access to field next [head] |
|
||||
| A.cs:119:14:119:30 | access to field head | semmle.label | access to field head |
|
||||
| A.cs:121:41:121:41 | access to local variable l [next, head] | semmle.label | access to local variable l [next, head] |
|
||||
| A.cs:121:41:121:41 | access to local variable l [next, next, ... (3)] | semmle.label | access to local variable l [next, next, ... (3)] |
|
||||
| A.cs:121:41:121:46 | access to field next [head] | semmle.label | access to field next [head] |
|
||||
| A.cs:121:41:121:46 | access to field next [next, head] | semmle.label | access to field next [next, head] |
|
||||
| A.cs:123:18:123:18 | access to local variable l [head] | semmle.label | access to local variable l [head] |
|
||||
| A.cs:123:18:123:23 | access to field head | semmle.label | access to field head |
|
||||
| B.cs:5:17:5:26 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| B.cs:6:18:6:34 | object creation of type Box1 [elem1] | semmle.label | object creation of type Box1 [elem1] |
|
||||
| B.cs:6:27:6:27 | access to local variable e | semmle.label | access to local variable e |
|
||||
| B.cs:7:18:7:29 | object creation of type Box2 [box1, elem1] | semmle.label | object creation of type Box2 [box1, elem1] |
|
||||
| B.cs:7:27:7:28 | access to local variable b1 [elem1] | semmle.label | access to local variable b1 [elem1] |
|
||||
| B.cs:8:14:8:15 | access to local variable b2 [box1, elem1] | semmle.label | access to local variable b2 [box1, elem1] |
|
||||
| B.cs:8:14:8:20 | access to field box1 [elem1] | semmle.label | access to field box1 [elem1] |
|
||||
| B.cs:8:14:8:26 | access to field elem1 | semmle.label | access to field elem1 |
|
||||
| B.cs:14:17:14:26 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| B.cs:15:18:15:34 | object creation of type Box1 [elem2] | semmle.label | object creation of type Box1 [elem2] |
|
||||
| B.cs:15:33:15:33 | access to local variable e | semmle.label | access to local variable e |
|
||||
| B.cs:16:18:16:29 | object creation of type Box2 [box1, elem2] | semmle.label | object creation of type Box2 [box1, elem2] |
|
||||
| B.cs:16:27:16:28 | access to local variable b1 [elem2] | semmle.label | access to local variable b1 [elem2] |
|
||||
| B.cs:18:14:18:15 | access to local variable b2 [box1, elem2] | semmle.label | access to local variable b2 [box1, elem2] |
|
||||
| B.cs:18:14:18:20 | access to field box1 [elem2] | semmle.label | access to field box1 [elem2] |
|
||||
| B.cs:18:14:18:26 | access to field elem2 | semmle.label | access to field elem2 |
|
||||
| C.cs:3:18:3:19 | [post] this access [s1] | semmle.label | [post] this access [s1] |
|
||||
| C.cs:3:23:3:32 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| C.cs:4:27:4:28 | [post] this access [s2] | semmle.label | [post] this access [s2] |
|
||||
| C.cs:4:32:4:41 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| C.cs:6:30:6:39 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| C.cs:7:18:7:19 | [post] this access [s5] | semmle.label | [post] this access [s5] |
|
||||
| C.cs:7:37:7:46 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| C.cs:8:30:8:39 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| C.cs:12:15:12:21 | object creation of type C [s1] | semmle.label | object creation of type C [s1] |
|
||||
| C.cs:12:15:12:21 | object creation of type C [s2] | semmle.label | object creation of type C [s2] |
|
||||
| C.cs:12:15:12:21 | object creation of type C [s3] | semmle.label | object creation of type C [s3] |
|
||||
| C.cs:12:15:12:21 | object creation of type C [s5] | semmle.label | object creation of type C [s5] |
|
||||
| C.cs:13:9:13:9 | access to local variable c [s1] | semmle.label | access to local variable c [s1] |
|
||||
| C.cs:13:9:13:9 | access to local variable c [s2] | semmle.label | access to local variable c [s2] |
|
||||
| C.cs:13:9:13:9 | access to local variable c [s3] | semmle.label | access to local variable c [s3] |
|
||||
| C.cs:13:9:13:9 | access to local variable c [s5] | semmle.label | access to local variable c [s5] |
|
||||
| C.cs:18:9:18:12 | [post] this access [s3] | semmle.label | [post] this access [s3] |
|
||||
| C.cs:18:19:18:28 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| C.cs:21:17:21:18 | this [s1] | semmle.label | this [s1] |
|
||||
| C.cs:21:17:21:18 | this [s2] | semmle.label | this [s2] |
|
||||
| C.cs:21:17:21:18 | this [s3] | semmle.label | this [s3] |
|
||||
| C.cs:21:17:21:18 | this [s5] | semmle.label | this [s5] |
|
||||
| C.cs:23:14:23:15 | access to field s1 | semmle.label | access to field s1 |
|
||||
| C.cs:23:14:23:15 | this access [s1] | semmle.label | this access [s1] |
|
||||
| C.cs:24:14:24:15 | access to field s2 | semmle.label | access to field s2 |
|
||||
| C.cs:24:14:24:15 | this access [s2] | semmle.label | this access [s2] |
|
||||
| C.cs:25:14:25:15 | access to field s3 | semmle.label | access to field s3 |
|
||||
| C.cs:25:14:25:15 | this access [s3] | semmle.label | this access [s3] |
|
||||
| C.cs:26:14:26:15 | access to field s4 | semmle.label | access to field s4 |
|
||||
| C.cs:27:14:27:15 | access to property s5 | semmle.label | access to property s5 |
|
||||
| C.cs:27:14:27:15 | this access [s5] | semmle.label | this access [s5] |
|
||||
| C.cs:28:14:28:15 | access to property s6 | semmle.label | access to property s6 |
|
||||
| D.cs:29:17:29:28 | object creation of type Object | semmle.label | object creation of type Object |
|
||||
| D.cs:31:17:31:37 | call to method Create [AutoProp] | semmle.label | call to method Create [AutoProp] |
|
||||
| D.cs:31:24:31:24 | access to local variable o | semmle.label | access to local variable o |
|
||||
| D.cs:32:14:32:14 | access to local variable d [AutoProp] | semmle.label | access to local variable d [AutoProp] |
|
||||
| D.cs:32:14:32:23 | access to property AutoProp | semmle.label | access to property AutoProp |
|
||||
| D.cs:37:13:37:33 | call to method Create [trivialPropField] | semmle.label | call to method Create [trivialPropField] |
|
||||
| D.cs:37:26:37:26 | access to local variable o | semmle.label | access to local variable o |
|
||||
| D.cs:39:14:39:14 | access to local variable d [trivialPropField] | semmle.label | access to local variable d [trivialPropField] |
|
||||
| D.cs:39:14:39:26 | access to property TrivialProp | semmle.label | access to property TrivialProp |
|
||||
| D.cs:40:14:40:14 | access to local variable d [trivialPropField] | semmle.label | access to local variable d [trivialPropField] |
|
||||
| D.cs:40:14:40:31 | access to field trivialPropField | semmle.label | access to field trivialPropField |
|
||||
| D.cs:41:14:41:14 | access to local variable d [trivialPropField] | semmle.label | access to local variable d [trivialPropField] |
|
||||
| D.cs:41:14:41:26 | access to property ComplexProp | semmle.label | access to property ComplexProp |
|
||||
| D.cs:43:13:43:33 | call to method Create [trivialPropField] | semmle.label | call to method Create [trivialPropField] |
|
||||
| D.cs:43:32:43:32 | access to local variable o | semmle.label | access to local variable o |
|
||||
| D.cs:45:14:45:14 | access to local variable d [trivialPropField] | semmle.label | access to local variable d [trivialPropField] |
|
||||
| D.cs:45:14:45:26 | access to property TrivialProp | semmle.label | access to property TrivialProp |
|
||||
| D.cs:46:14:46:14 | access to local variable d [trivialPropField] | semmle.label | access to local variable d [trivialPropField] |
|
||||
| D.cs:46:14:46:31 | access to field trivialPropField | semmle.label | access to field trivialPropField |
|
||||
| D.cs:47:14:47:14 | access to local variable d [trivialPropField] | semmle.label | access to local variable d [trivialPropField] |
|
||||
| D.cs:47:14:47:26 | access to property ComplexProp | semmle.label | access to property ComplexProp |
|
||||
| E.cs:22:17:22:28 | object creation of type Object | semmle.label | object creation of type Object |
|
||||
| E.cs:23:17:23:26 | call to method CreateS [Field] | semmle.label | call to method CreateS [Field] |
|
||||
| E.cs:23:25:23:25 | access to local variable o | semmle.label | access to local variable o |
|
||||
| E.cs:24:14:24:14 | access to local variable s [Field] | semmle.label | access to local variable s [Field] |
|
||||
| E.cs:24:14:24:20 | access to field Field | semmle.label | access to field Field |
|
||||
| F.cs:10:17:10:28 | object creation of type Object | semmle.label | object creation of type Object |
|
||||
| F.cs:11:17:11:31 | call to method Create [Field1] | semmle.label | call to method Create [Field1] |
|
||||
| F.cs:11:24:11:24 | access to local variable o | semmle.label | access to local variable o |
|
||||
| F.cs:12:14:12:14 | access to local variable f [Field1] | semmle.label | access to local variable f [Field1] |
|
||||
| F.cs:12:14:12:21 | access to field Field1 | semmle.label | access to field Field1 |
|
||||
| F.cs:15:13:15:27 | call to method Create [Field2] | semmle.label | call to method Create [Field2] |
|
||||
| F.cs:15:26:15:26 | access to local variable o | semmle.label | access to local variable o |
|
||||
| F.cs:17:14:17:14 | access to local variable f [Field2] | semmle.label | access to local variable f [Field2] |
|
||||
| F.cs:17:14:17:21 | access to field Field2 | semmle.label | access to field Field2 |
|
||||
| F.cs:19:13:19:34 | object creation of type F [Field1] | semmle.label | object creation of type F [Field1] |
|
||||
| F.cs:19:32:19:32 | access to local variable o | semmle.label | access to local variable o |
|
||||
| F.cs:20:14:20:14 | access to local variable f [Field1] | semmle.label | access to local variable f [Field1] |
|
||||
| F.cs:20:14:20:21 | access to field Field1 | semmle.label | access to field Field1 |
|
||||
| F.cs:23:13:23:34 | object creation of type F [Field2] | semmle.label | object creation of type F [Field2] |
|
||||
| F.cs:23:32:23:32 | access to local variable o | semmle.label | access to local variable o |
|
||||
| F.cs:25:14:25:14 | access to local variable f [Field2] | semmle.label | access to local variable f [Field2] |
|
||||
| F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 |
|
||||
| G.cs:7:18:7:27 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| G.cs:9:9:9:9 | [post] access to local variable b [Box1, Elem] | semmle.label | [post] access to local variable b [Box1, Elem] |
|
||||
| G.cs:9:9:9:14 | [post] access to field Box1 [Elem] | semmle.label | [post] access to field Box1 [Elem] |
|
||||
| G.cs:9:23:9:23 | access to local variable e | semmle.label | access to local variable e |
|
||||
| G.cs:10:18:10:18 | access to local variable b [Box1, Elem] | semmle.label | access to local variable b [Box1, Elem] |
|
||||
| G.cs:15:18:15:27 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| G.cs:17:9:17:9 | [post] access to local variable b [Box1, Elem] | semmle.label | [post] access to local variable b [Box1, Elem] |
|
||||
| G.cs:17:9:17:14 | [post] access to field Box1 [Elem] | semmle.label | [post] access to field Box1 [Elem] |
|
||||
| G.cs:17:24:17:24 | access to local variable e | semmle.label | access to local variable e |
|
||||
| G.cs:18:18:18:18 | access to local variable b [Box1, Elem] | semmle.label | access to local variable b [Box1, Elem] |
|
||||
| G.cs:23:18:23:27 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| G.cs:25:9:25:9 | [post] access to local variable b [Box1, Elem] | semmle.label | [post] access to local variable b [Box1, Elem] |
|
||||
| G.cs:25:9:25:19 | [post] call to method GetBox1 [Elem] | semmle.label | [post] call to method GetBox1 [Elem] |
|
||||
| G.cs:25:28:25:28 | access to local variable e | semmle.label | access to local variable e |
|
||||
| G.cs:26:18:26:18 | access to local variable b [Box1, Elem] | semmle.label | access to local variable b [Box1, Elem] |
|
||||
| G.cs:31:18:31:27 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| G.cs:33:9:33:9 | [post] access to local variable b [Box1, Elem] | semmle.label | [post] access to local variable b [Box1, Elem] |
|
||||
| G.cs:33:9:33:19 | [post] call to method GetBox1 [Elem] | semmle.label | [post] call to method GetBox1 [Elem] |
|
||||
| G.cs:33:29:33:29 | access to local variable e | semmle.label | access to local variable e |
|
||||
| G.cs:34:18:34:18 | access to local variable b [Box1, Elem] | semmle.label | access to local variable b [Box1, Elem] |
|
||||
| G.cs:37:38:37:39 | b2 [Box1, Elem] | semmle.label | b2 [Box1, Elem] |
|
||||
| G.cs:39:14:39:15 | access to parameter b2 [Box1, Elem] | semmle.label | access to parameter b2 [Box1, Elem] |
|
||||
| G.cs:39:14:39:25 | call to method GetBox1 [Elem] | semmle.label | call to method GetBox1 [Elem] |
|
||||
| G.cs:39:14:39:35 | call to method GetElem | semmle.label | call to method GetElem |
|
||||
| G.cs:44:18:44:27 | object creation of type Elem | semmle.label | object creation of type Elem |
|
||||
| G.cs:46:9:46:16 | [post] access to field boxfield [Box1, Elem] | semmle.label | [post] access to field boxfield [Box1, Elem] |
|
||||
| G.cs:46:9:46:16 | [post] this access [boxfield, Box1, ... (3)] | semmle.label | [post] this access [boxfield, Box1, ... (3)] |
|
||||
| G.cs:46:9:46:21 | [post] access to field Box1 [Elem] | semmle.label | [post] access to field Box1 [Elem] |
|
||||
| G.cs:46:30:46:30 | access to local variable e | semmle.label | access to local variable e |
|
||||
| G.cs:47:9:47:13 | this access [boxfield, Box1, ... (3)] | semmle.label | this access [boxfield, Box1, ... (3)] |
|
||||
| G.cs:50:18:50:20 | this [boxfield, Box1, ... (3)] | semmle.label | this [boxfield, Box1, ... (3)] |
|
||||
| G.cs:52:14:52:21 | access to field boxfield [Box1, Elem] | semmle.label | access to field boxfield [Box1, Elem] |
|
||||
| G.cs:52:14:52:21 | this access [boxfield, Box1, ... (3)] | semmle.label | this access [boxfield, Box1, ... (3)] |
|
||||
| G.cs:52:14:52:26 | access to field Box1 [Elem] | semmle.label | access to field Box1 [Elem] |
|
||||
| G.cs:52:14:52:31 | access to field Elem | semmle.label | access to field Elem |
|
||||
#select
|
||||
| A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:23 | object creation of type C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:23 | object creation of type C | object creation of type C |
|
||||
| A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:22 | object creation of type C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:22 | object creation of type C1 | object creation of type C1 |
|
||||
|
||||
@@ -192,6 +192,159 @@ edges
|
||||
| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | Splitting.cs:34:19:34:19 | access to local variable x |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element |
|
||||
nodes
|
||||
| Capture.cs:7:20:7:26 | tainted | semmle.label | tainted |
|
||||
| Capture.cs:9:9:13:9 | SSA capture def(tainted) | semmle.label | SSA capture def(tainted) |
|
||||
| Capture.cs:12:19:12:24 | access to local variable sink27 | semmle.label | access to local variable sink27 |
|
||||
| Capture.cs:14:9:14:20 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:18:13:22:13 | SSA capture def(tainted) | semmle.label | SSA capture def(tainted) |
|
||||
| Capture.cs:21:23:21:28 | access to local variable sink28 | semmle.label | access to local variable sink28 |
|
||||
| Capture.cs:25:9:25:20 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:27:43:32:9 | SSA capture def(tainted) | semmle.label | SSA capture def(tainted) |
|
||||
| Capture.cs:30:19:30:24 | access to local variable sink29 | semmle.label | access to local variable sink29 |
|
||||
| Capture.cs:33:9:33:40 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:57:13:57:35 | SSA def(sink30) | semmle.label | SSA def(sink30) |
|
||||
| Capture.cs:57:22:57:35 | "taint source" | semmle.label | "taint source" |
|
||||
| Capture.cs:59:9:59:21 | SSA call def(sink30) | semmle.label | SSA call def(sink30) |
|
||||
| Capture.cs:60:15:60:20 | access to local variable sink30 | semmle.label | access to local variable sink30 |
|
||||
| Capture.cs:67:17:67:39 | SSA def(sink31) | semmle.label | SSA def(sink31) |
|
||||
| Capture.cs:67:26:67:39 | "taint source" | semmle.label | "taint source" |
|
||||
| Capture.cs:71:9:71:21 | SSA call def(sink31) | semmle.label | SSA call def(sink31) |
|
||||
| Capture.cs:72:15:72:20 | access to local variable sink31 | semmle.label | access to local variable sink31 |
|
||||
| Capture.cs:77:13:77:35 | SSA def(sink32) | semmle.label | SSA def(sink32) |
|
||||
| Capture.cs:77:22:77:35 | "taint source" | semmle.label | "taint source" |
|
||||
| Capture.cs:80:9:80:41 | SSA call def(sink32) | semmle.label | SSA call def(sink32) |
|
||||
| Capture.cs:81:15:81:20 | access to local variable sink32 | semmle.label | access to local variable sink32 |
|
||||
| Capture.cs:101:25:101:31 | tainted | semmle.label | tainted |
|
||||
| Capture.cs:108:9:108:25 | SSA call def(sink33) | semmle.label | SSA call def(sink33) |
|
||||
| Capture.cs:108:9:108:25 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:109:15:109:20 | access to local variable sink33 | semmle.label | access to local variable sink33 |
|
||||
| Capture.cs:120:9:120:25 | SSA call def(sink34) | semmle.label | SSA call def(sink34) |
|
||||
| Capture.cs:120:9:120:25 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:121:15:121:20 | access to local variable sink34 | semmle.label | access to local variable sink34 |
|
||||
| Capture.cs:129:9:129:45 | SSA call def(sink35) | semmle.label | SSA call def(sink35) |
|
||||
| Capture.cs:129:9:129:45 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:130:15:130:20 | access to local variable sink35 | semmle.label | access to local variable sink35 |
|
||||
| Capture.cs:136:22:136:38 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:136:22:136:38 | call to local function CaptureThrough4 | semmle.label | call to local function CaptureThrough4 |
|
||||
| Capture.cs:137:15:137:20 | access to local variable sink36 | semmle.label | access to local variable sink36 |
|
||||
| Capture.cs:144:9:144:32 | SSA call def(sink37) | semmle.label | SSA call def(sink37) |
|
||||
| Capture.cs:144:25:144:31 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| Capture.cs:145:15:145:20 | access to local variable sink37 | semmle.label | access to local variable sink37 |
|
||||
| Capture.cs:170:22:170:32 | call to local function Id | semmle.label | call to local function Id |
|
||||
| Capture.cs:170:25:170:31 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| Capture.cs:171:15:171:20 | access to local variable sink38 | semmle.label | access to local variable sink38 |
|
||||
| GlobalDataFlow.cs:17:27:17:40 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | semmle.label | access to field SinkField0 |
|
||||
| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | semmle.label | sinkParam2 |
|
||||
| GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | semmle.label | access to parameter sinkParam2 |
|
||||
| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:53:15:53:15 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:53:24:53:24 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:56:37:56:37 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:56:46:56:46 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | semmle.label | access to parameter nonSinkParam0 |
|
||||
| GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | semmle.label | access to parameter nonSinkParam0 |
|
||||
| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:70:21:70:46 | call to method Return | semmle.label | call to method Return |
|
||||
| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | semmle.label | access to local variable sink0 |
|
||||
| GlobalDataFlow.cs:72:21:72:101 | (...) ... | semmle.label | (...) ... |
|
||||
| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | semmle.label | call to method Invoke |
|
||||
| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | semmle.label | access to local variable sink0 |
|
||||
| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | semmle.label | access to local variable sink1 |
|
||||
| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | semmle.label | access to local variable sink1 |
|
||||
| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | semmle.label | SSA def(sink2) |
|
||||
| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | semmle.label | access to local variable sink2 |
|
||||
| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | semmle.label | access to local variable sink2 |
|
||||
| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | semmle.label | SSA def(sink3) |
|
||||
| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | semmle.label | access to local variable sink3 |
|
||||
| GlobalDataFlow.cs:135:21:135:34 | delegate call | semmle.label | delegate call |
|
||||
| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | semmle.label | access to local variable sink3 |
|
||||
| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | semmle.label | access to local variable sink4 |
|
||||
| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | semmle.label | call to method ApplyFunc |
|
||||
| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | semmle.label | access to local variable sink4 |
|
||||
| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | semmle.label | access to local variable sink5 |
|
||||
| GlobalDataFlow.cs:153:21:153:25 | call to method Out | semmle.label | call to method Out |
|
||||
| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | semmle.label | access to local variable sink6 |
|
||||
| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) | semmle.label | SSA def(sink7) |
|
||||
| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | semmle.label | access to local variable sink7 |
|
||||
| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | semmle.label | SSA def(sink8) |
|
||||
| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | semmle.label | access to local variable sink8 |
|
||||
| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | semmle.label | call to method TaintedParam |
|
||||
| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | semmle.label | access to local variable sink23 |
|
||||
| GlobalDataFlow.cs:179:35:179:48 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:180:21:180:26 | delegate call | semmle.label | delegate call |
|
||||
| GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | semmle.label | access to local variable sink9 |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> | semmle.label | [output] delegate creation of type Func<String> |
|
||||
| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | semmle.label | access to property OutProperty |
|
||||
| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 |
|
||||
| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | semmle.label | sinkParam0 |
|
||||
| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 |
|
||||
| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 |
|
||||
| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | semmle.label | sinkParam1 |
|
||||
| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 |
|
||||
| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | semmle.label | sinkParam3 |
|
||||
| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 |
|
||||
| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | semmle.label | sinkParam4 |
|
||||
| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 |
|
||||
| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | semmle.label | sinkParam5 |
|
||||
| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 |
|
||||
| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | semmle.label | sinkParam6 |
|
||||
| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 |
|
||||
| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | semmle.label | sinkParam7 |
|
||||
| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 |
|
||||
| GlobalDataFlow.cs:318:16:318:29 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) | semmle.label | SSA def(x) |
|
||||
| GlobalDataFlow.cs:323:13:323:26 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) | semmle.label | SSA def(x) |
|
||||
| GlobalDataFlow.cs:328:13:328:26 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:359:41:359:41 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:359:41:359:41 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:361:11:361:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:361:11:361:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:373:52:373:52 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:373:52:373:52 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:373:52:373:52 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:375:11:375:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:375:11:375:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:375:11:375:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:378:39:378:45 | tainted | semmle.label | tainted |
|
||||
| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | semmle.label | access to local variable sink11 |
|
||||
| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | semmle.label | access to local variable sink11 |
|
||||
| GlobalDataFlow.cs:404:9:404:11 | value | semmle.label | value |
|
||||
| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | semmle.label | access to local variable sink20 |
|
||||
| GlobalDataFlow.cs:415:22:415:35 | "taint source" | semmle.label | "taint source" |
|
||||
| Splitting.cs:3:28:3:34 | tainted | semmle.label | tainted |
|
||||
| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | semmle.label | [b (line 3): false] call to method Return |
|
||||
| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | semmle.label | [b (line 3): true] call to method Return |
|
||||
| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | semmle.label | [b (line 3): false] access to parameter tainted |
|
||||
| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | semmle.label | [b (line 3): true] access to parameter tainted |
|
||||
| Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | semmle.label | [b (line 3): false] access to local variable x |
|
||||
| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | semmle.label | [b (line 3): true] access to local variable x |
|
||||
| Splitting.cs:11:19:11:19 | access to local variable x | semmle.label | access to local variable x |
|
||||
| Splitting.cs:21:9:21:11 | value | semmle.label | value |
|
||||
| Splitting.cs:21:28:21:32 | access to parameter value | semmle.label | access to parameter value |
|
||||
| Splitting.cs:24:28:24:34 | tainted | semmle.label | tainted |
|
||||
| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | semmle.label | [b (line 24): false] access to parameter tainted |
|
||||
| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | semmle.label | [b (line 24): true] access to parameter tainted |
|
||||
| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | semmle.label | [b (line 24): false] dynamic access to element |
|
||||
| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | semmle.label | [b (line 24): true] dynamic access to element |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | semmle.label | [b (line 24): false] access to parameter tainted |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | semmle.label | [b (line 24): true] access to parameter tainted |
|
||||
| Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | semmle.label | [b (line 24): false] access to local variable x |
|
||||
| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | semmle.label | [b (line 24): true] access to local variable x |
|
||||
| Splitting.cs:34:19:34:19 | access to local variable x | semmle.label | access to local variable x |
|
||||
#select
|
||||
| Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | Splitting.cs:24:28:24:34 | tainted | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | [b (line 24): false] access to local variable x |
|
||||
| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | Splitting.cs:24:28:24:34 | tainted | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | [b (line 24): true] access to local variable x |
|
||||
|
||||
@@ -239,6 +239,205 @@ edges
|
||||
| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | Splitting.cs:34:19:34:19 | access to local variable x |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element |
|
||||
nodes
|
||||
| Capture.cs:7:20:7:26 | tainted | semmle.label | tainted |
|
||||
| Capture.cs:9:9:13:9 | SSA capture def(tainted) | semmle.label | SSA capture def(tainted) |
|
||||
| Capture.cs:12:19:12:24 | access to local variable sink27 | semmle.label | access to local variable sink27 |
|
||||
| Capture.cs:14:9:14:20 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:18:13:22:13 | SSA capture def(tainted) | semmle.label | SSA capture def(tainted) |
|
||||
| Capture.cs:21:23:21:28 | access to local variable sink28 | semmle.label | access to local variable sink28 |
|
||||
| Capture.cs:25:9:25:20 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:27:43:32:9 | SSA capture def(tainted) | semmle.label | SSA capture def(tainted) |
|
||||
| Capture.cs:30:19:30:24 | access to local variable sink29 | semmle.label | access to local variable sink29 |
|
||||
| Capture.cs:33:9:33:40 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:57:13:57:35 | SSA def(sink30) | semmle.label | SSA def(sink30) |
|
||||
| Capture.cs:57:22:57:35 | "taint source" | semmle.label | "taint source" |
|
||||
| Capture.cs:59:9:59:21 | SSA call def(sink30) | semmle.label | SSA call def(sink30) |
|
||||
| Capture.cs:60:15:60:20 | access to local variable sink30 | semmle.label | access to local variable sink30 |
|
||||
| Capture.cs:67:17:67:39 | SSA def(sink31) | semmle.label | SSA def(sink31) |
|
||||
| Capture.cs:67:26:67:39 | "taint source" | semmle.label | "taint source" |
|
||||
| Capture.cs:71:9:71:21 | SSA call def(sink31) | semmle.label | SSA call def(sink31) |
|
||||
| Capture.cs:72:15:72:20 | access to local variable sink31 | semmle.label | access to local variable sink31 |
|
||||
| Capture.cs:77:13:77:35 | SSA def(sink32) | semmle.label | SSA def(sink32) |
|
||||
| Capture.cs:77:22:77:35 | "taint source" | semmle.label | "taint source" |
|
||||
| Capture.cs:80:9:80:41 | SSA call def(sink32) | semmle.label | SSA call def(sink32) |
|
||||
| Capture.cs:81:15:81:20 | access to local variable sink32 | semmle.label | access to local variable sink32 |
|
||||
| Capture.cs:101:25:101:31 | tainted | semmle.label | tainted |
|
||||
| Capture.cs:108:9:108:25 | SSA call def(sink33) | semmle.label | SSA call def(sink33) |
|
||||
| Capture.cs:108:9:108:25 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:109:15:109:20 | access to local variable sink33 | semmle.label | access to local variable sink33 |
|
||||
| Capture.cs:120:9:120:25 | SSA call def(sink34) | semmle.label | SSA call def(sink34) |
|
||||
| Capture.cs:120:9:120:25 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:121:15:121:20 | access to local variable sink34 | semmle.label | access to local variable sink34 |
|
||||
| Capture.cs:129:9:129:45 | SSA call def(sink35) | semmle.label | SSA call def(sink35) |
|
||||
| Capture.cs:129:9:129:45 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:130:15:130:20 | access to local variable sink35 | semmle.label | access to local variable sink35 |
|
||||
| Capture.cs:136:22:136:38 | [implicit argument] tainted | semmle.label | [implicit argument] tainted |
|
||||
| Capture.cs:136:22:136:38 | call to local function CaptureThrough4 | semmle.label | call to local function CaptureThrough4 |
|
||||
| Capture.cs:137:15:137:20 | access to local variable sink36 | semmle.label | access to local variable sink36 |
|
||||
| Capture.cs:144:9:144:32 | SSA call def(sink37) | semmle.label | SSA call def(sink37) |
|
||||
| Capture.cs:144:25:144:31 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| Capture.cs:145:15:145:20 | access to local variable sink37 | semmle.label | access to local variable sink37 |
|
||||
| Capture.cs:170:22:170:32 | call to local function Id | semmle.label | call to local function Id |
|
||||
| Capture.cs:170:25:170:31 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| Capture.cs:171:15:171:20 | access to local variable sink38 | semmle.label | access to local variable sink38 |
|
||||
| GlobalDataFlow.cs:17:27:17:40 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | semmle.label | access to field SinkField0 |
|
||||
| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | semmle.label | sinkParam2 |
|
||||
| GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | semmle.label | access to parameter sinkParam2 |
|
||||
| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:53:15:53:15 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:53:24:53:24 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:56:37:56:37 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:56:46:56:46 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | semmle.label | access to parameter nonSinkParam0 |
|
||||
| GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | semmle.label | access to parameter nonSinkParam0 |
|
||||
| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:70:21:70:46 | call to method Return | semmle.label | call to method Return |
|
||||
| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | semmle.label | access to property SinkProperty0 |
|
||||
| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | semmle.label | access to local variable sink0 |
|
||||
| GlobalDataFlow.cs:72:21:72:101 | (...) ... | semmle.label | (...) ... |
|
||||
| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | semmle.label | call to method Invoke |
|
||||
| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | semmle.label | access to local variable sink0 |
|
||||
| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | semmle.label | access to local variable sink1 |
|
||||
| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | semmle.label | access to local variable sink1 |
|
||||
| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | semmle.label | SSA def(sink2) |
|
||||
| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | semmle.label | access to local variable sink2 |
|
||||
| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | semmle.label | access to local variable sink2 |
|
||||
| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | semmle.label | SSA def(sink3) |
|
||||
| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | semmle.label | access to local variable sink3 |
|
||||
| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | semmle.label | call to method SelectEven |
|
||||
| GlobalDataFlow.cs:80:23:80:65 | (...) ... | semmle.label | (...) ... |
|
||||
| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | semmle.label | access to local variable sink13 |
|
||||
| GlobalDataFlow.cs:82:23:82:74 | (...) ... | semmle.label | (...) ... |
|
||||
| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func<String,String> | semmle.label | [output] delegate creation of type Func<String,String> |
|
||||
| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | semmle.label | access to local variable sink14 |
|
||||
| GlobalDataFlow.cs:84:23:84:74 | (...) ... | semmle.label | (...) ... |
|
||||
| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | semmle.label | [output] (...) => ... |
|
||||
| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | semmle.label | access to local variable sink15 |
|
||||
| GlobalDataFlow.cs:86:70:86:121 | (...) ... | semmle.label | (...) ... |
|
||||
| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | semmle.label | [output] (...) => ... |
|
||||
| GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | semmle.label | access to local variable sink16 |
|
||||
| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | semmle.label | access to local variable sink14 |
|
||||
| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | semmle.label | [output] (...) => ... |
|
||||
| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | semmle.label | [output] (...) => ... |
|
||||
| GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | semmle.label | access to local variable sink17 |
|
||||
| GlobalDataFlow.cs:90:75:90:88 | call to method First | semmle.label | call to method First |
|
||||
| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | semmle.label | [output] (...) => ... |
|
||||
| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | semmle.label | [output] (...) => ... |
|
||||
| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | semmle.label | access to local variable sink18 |
|
||||
| GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | semmle.label | access to local variable sink21 |
|
||||
| GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | semmle.label | access to local variable sink22 |
|
||||
| GlobalDataFlow.cs:135:21:135:34 | delegate call | semmle.label | delegate call |
|
||||
| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | semmle.label | access to local variable sink3 |
|
||||
| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | semmle.label | access to local variable sink4 |
|
||||
| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | semmle.label | call to method ApplyFunc |
|
||||
| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | semmle.label | access to local variable sink4 |
|
||||
| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | semmle.label | access to local variable sink5 |
|
||||
| GlobalDataFlow.cs:153:21:153:25 | call to method Out | semmle.label | call to method Out |
|
||||
| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | semmle.label | access to local variable sink6 |
|
||||
| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) | semmle.label | SSA def(sink7) |
|
||||
| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | semmle.label | access to local variable sink7 |
|
||||
| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | semmle.label | SSA def(sink8) |
|
||||
| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | semmle.label | access to local variable sink8 |
|
||||
| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | semmle.label | call to method OutYield |
|
||||
| GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | semmle.label | access to local variable sink12 |
|
||||
| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | semmle.label | call to method TaintedParam |
|
||||
| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | semmle.label | access to local variable sink23 |
|
||||
| GlobalDataFlow.cs:179:35:179:48 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:180:21:180:26 | delegate call | semmle.label | delegate call |
|
||||
| GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | semmle.label | access to local variable sink9 |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> | semmle.label | [output] delegate creation of type Func<String> |
|
||||
| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | semmle.label | access to property OutProperty |
|
||||
| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 |
|
||||
| GlobalDataFlow.cs:205:39:205:45 | tainted | semmle.label | tainted |
|
||||
| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | semmle.label | sinkParam10 |
|
||||
| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | semmle.label | access to parameter sinkParam10 |
|
||||
| GlobalDataFlow.cs:209:71:209:71 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:209:89:209:89 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | semmle.label | [output] access to local variable f1 |
|
||||
| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | semmle.label | access to local variable sink24 |
|
||||
| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | semmle.label | [output] access to local variable f2 |
|
||||
| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | semmle.label | access to local variable sink25 |
|
||||
| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | semmle.label | access to parameter tainted |
|
||||
| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func<String,String> | semmle.label | [output] delegate creation of type Func<String,String> |
|
||||
| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | semmle.label | access to local variable sink26 |
|
||||
| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | semmle.label | sinkParam0 |
|
||||
| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 |
|
||||
| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 |
|
||||
| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | semmle.label | sinkParam1 |
|
||||
| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 |
|
||||
| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | semmle.label | sinkParam3 |
|
||||
| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 |
|
||||
| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | semmle.label | sinkParam4 |
|
||||
| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 |
|
||||
| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | semmle.label | sinkParam5 |
|
||||
| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 |
|
||||
| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | semmle.label | sinkParam6 |
|
||||
| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 |
|
||||
| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | semmle.label | sinkParam7 |
|
||||
| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 |
|
||||
| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | semmle.label | sinkParam8 |
|
||||
| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 |
|
||||
| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | semmle.label | sinkParam9 |
|
||||
| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 |
|
||||
| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | semmle.label | sinkParam11 |
|
||||
| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 |
|
||||
| GlobalDataFlow.cs:318:16:318:29 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) | semmle.label | SSA def(x) |
|
||||
| GlobalDataFlow.cs:323:13:323:26 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) | semmle.label | SSA def(x) |
|
||||
| GlobalDataFlow.cs:328:13:328:26 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:334:22:334:35 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:334:22:334:35 | "taint source" | semmle.label | "taint source" |
|
||||
| GlobalDataFlow.cs:359:41:359:41 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:359:41:359:41 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:361:11:361:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:361:11:361:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:373:52:373:52 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:373:52:373:52 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:373:52:373:52 | x | semmle.label | x |
|
||||
| GlobalDataFlow.cs:375:11:375:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:375:11:375:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:375:11:375:11 | access to parameter x | semmle.label | access to parameter x |
|
||||
| GlobalDataFlow.cs:378:39:378:45 | tainted | semmle.label | tainted |
|
||||
| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | semmle.label | access to local variable sink11 |
|
||||
| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | semmle.label | access to local variable sink11 |
|
||||
| GlobalDataFlow.cs:404:9:404:11 | value | semmle.label | value |
|
||||
| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | semmle.label | access to local variable sink20 |
|
||||
| GlobalDataFlow.cs:415:22:415:35 | "taint source" | semmle.label | "taint source" |
|
||||
| Splitting.cs:3:28:3:34 | tainted | semmle.label | tainted |
|
||||
| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | semmle.label | [b (line 3): false] call to method Return |
|
||||
| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | semmle.label | [b (line 3): true] call to method Return |
|
||||
| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | semmle.label | [b (line 3): false] access to parameter tainted |
|
||||
| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | semmle.label | [b (line 3): true] access to parameter tainted |
|
||||
| Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | semmle.label | [b (line 3): false] access to local variable x |
|
||||
| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | semmle.label | [b (line 3): true] access to local variable x |
|
||||
| Splitting.cs:11:19:11:19 | access to local variable x | semmle.label | access to local variable x |
|
||||
| Splitting.cs:21:9:21:11 | value | semmle.label | value |
|
||||
| Splitting.cs:21:28:21:32 | access to parameter value | semmle.label | access to parameter value |
|
||||
| Splitting.cs:24:28:24:34 | tainted | semmle.label | tainted |
|
||||
| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | semmle.label | [b (line 24): false] access to parameter tainted |
|
||||
| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | semmle.label | [b (line 24): true] access to parameter tainted |
|
||||
| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | semmle.label | [b (line 24): false] dynamic access to element |
|
||||
| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | semmle.label | [b (line 24): true] dynamic access to element |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | semmle.label | [b (line 24): false] access to parameter tainted |
|
||||
| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | semmle.label | [b (line 24): true] access to parameter tainted |
|
||||
| Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | semmle.label | [b (line 24): false] access to local variable x |
|
||||
| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | semmle.label | [b (line 24): true] access to local variable x |
|
||||
| Splitting.cs:34:19:34:19 | access to local variable x | semmle.label | access to local variable x |
|
||||
#select
|
||||
| Capture.cs:12:19:12:24 | access to local variable sink27 | Capture.cs:7:20:7:26 | tainted | Capture.cs:12:19:12:24 | access to local variable sink27 | access to local variable sink27 |
|
||||
| Capture.cs:21:23:21:28 | access to local variable sink28 | Capture.cs:7:20:7:26 | tainted | Capture.cs:21:23:21:28 | access to local variable sink28 | access to local variable sink28 |
|
||||
|
||||
19
csharp/ql/test/library-tests/ir/ir/collections.cs
Normal file
19
csharp/ql/test/library-tests/ir/ir/collections.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class Collections
|
||||
{
|
||||
class MyClass
|
||||
{
|
||||
public string a;
|
||||
public string b;
|
||||
}
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
var dict = new Dictionary<int, MyClass>()
|
||||
{
|
||||
{ 0, new MyClass { a="Hello", b="World" } },
|
||||
{ 1, new MyClass { a="Foo", b="Bar" } }
|
||||
};
|
||||
}
|
||||
}
|
||||
40
csharp/ql/test/library-tests/ir/ir/jumps.cs
Normal file
40
csharp/ql/test/library-tests/ir/ir/jumps.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
class Jumps
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
if (i == 3)
|
||||
continue;
|
||||
else if (i == 5)
|
||||
break;
|
||||
Console.WriteLine("BreakAndContinue");
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < 10 ; )
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int a = 0;
|
||||
while (true)
|
||||
{
|
||||
a++;
|
||||
if (a == 5)
|
||||
continue;
|
||||
if (a == 10)
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
if (i == 5)
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
Console.WriteLine("Done");
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,17 @@ public class ObjCreation
|
||||
x = _x;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SomeFun(MyClass x)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
MyClass obj = new MyClass(100);
|
||||
MyClass obj_initlist = new MyClass { x = 101 };
|
||||
int a = obj.x;
|
||||
|
||||
SomeFun(new MyClass(100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,50 @@ casts.cs:
|
||||
# 11| v0_20(Void) = UnmodeledUse : mu*
|
||||
# 11| v0_21(Void) = ExitFunction :
|
||||
|
||||
collections.cs:
|
||||
# 11| System.Void Collections.Main()
|
||||
# 11| Block 0
|
||||
# 11| v0_0(Void) = EnterFunction :
|
||||
# 11| mu0_1(null) = AliasedDefinition :
|
||||
# 11| mu0_2(null) = UnmodeledDefinition :
|
||||
# 13| r0_3(glval<Dictionary<Int32,MyClass>>) = VariableAddress[dict] :
|
||||
# 13| r0_4(Dictionary<Int32,MyClass>) = NewObj :
|
||||
# 13| r0_5(glval<null>) = FunctionAddress[Dictionary] :
|
||||
# 13| v0_6(Void) = Call : func:r0_5, this:r0_4
|
||||
# 13| mu0_7(null) = ^CallSideEffect : ~mu0_2
|
||||
# 15| r0_8(glval<null>) = FunctionAddress[Add] :
|
||||
# 15| r0_9(Int32) = Constant[0] :
|
||||
# 15| r0_10(MyClass) = NewObj :
|
||||
# 15| r0_11(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 15| v0_12(Void) = Call : func:r0_11, this:r0_10
|
||||
# 15| mu0_13(null) = ^CallSideEffect : ~mu0_2
|
||||
# 15| r0_14(String) = StringConstant["Hello"] :
|
||||
# 15| r0_15(glval<String>) = FieldAddress[a] : r0_10
|
||||
# 15| mu0_16(String) = Store : &:r0_15, r0_14
|
||||
# 15| r0_17(String) = StringConstant["World"] :
|
||||
# 15| r0_18(glval<String>) = FieldAddress[b] : r0_10
|
||||
# 15| mu0_19(String) = Store : &:r0_18, r0_17
|
||||
# 15| v0_20(Void) = Call : func:r0_8, this:r0_4, 0:r0_9, 1:r0_10
|
||||
# 15| mu0_21(null) = ^CallSideEffect : ~mu0_2
|
||||
# 16| r0_22(glval<null>) = FunctionAddress[Add] :
|
||||
# 16| r0_23(Int32) = Constant[1] :
|
||||
# 16| r0_24(MyClass) = NewObj :
|
||||
# 16| r0_25(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 16| v0_26(Void) = Call : func:r0_25, this:r0_24
|
||||
# 16| mu0_27(null) = ^CallSideEffect : ~mu0_2
|
||||
# 16| r0_28(String) = StringConstant["Foo"] :
|
||||
# 16| r0_29(glval<String>) = FieldAddress[a] : r0_24
|
||||
# 16| mu0_30(String) = Store : &:r0_29, r0_28
|
||||
# 16| r0_31(String) = StringConstant["Bar"] :
|
||||
# 16| r0_32(glval<String>) = FieldAddress[b] : r0_24
|
||||
# 16| mu0_33(String) = Store : &:r0_32, r0_31
|
||||
# 16| v0_34(Void) = Call : func:r0_22, this:r0_4, 0:r0_23, 1:r0_24
|
||||
# 16| mu0_35(null) = ^CallSideEffect : ~mu0_2
|
||||
# 13| mu0_36(Dictionary<Int32,MyClass>) = Store : &:r0_3, r0_4
|
||||
# 11| v0_37(Void) = ReturnVoid :
|
||||
# 11| v0_38(Void) = UnmodeledUse : mu*
|
||||
# 11| v0_39(Void) = ExitFunction :
|
||||
|
||||
constructor_init.cs:
|
||||
# 5| System.Void BaseClass..ctor()
|
||||
# 5| Block 0
|
||||
@@ -534,7 +578,7 @@ inheritance_polymorphism.cs:
|
||||
# 33| v0_28(Void) = Call : func:r0_27, this:r0_26
|
||||
# 33| mu0_29(null) = ^CallSideEffect : ~mu0_2
|
||||
# 33| r0_30(A) = Convert : r0_26
|
||||
# 33| mu0_31(C) = Store : &:r0_25, r0_30
|
||||
# 33| mu0_31(A) = Store : &:r0_25, r0_26
|
||||
# 34| r0_32(glval<A>) = VariableAddress[objC] :
|
||||
# 34| r0_33(A) = Load : &:r0_32, ~mu0_2
|
||||
# 34| r0_34(glval<null>) = FunctionAddress[function] :
|
||||
@@ -547,21 +591,23 @@ inheritance_polymorphism.cs:
|
||||
isexpr.cs:
|
||||
# 8| System.Void IsExpr.Main()
|
||||
# 8| Block 0
|
||||
# 8| v0_0(Void) = EnterFunction :
|
||||
# 8| mu0_1(null) = AliasedDefinition :
|
||||
# 8| mu0_2(null) = UnmodeledDefinition :
|
||||
# 10| r0_3(glval<Is_A>) = VariableAddress[obj] :
|
||||
# 10| r0_4(null) = Constant[null] :
|
||||
# 10| mu0_5(Is_A) = Store : &:r0_3, r0_4
|
||||
# 12| r0_6(glval<Object>) = VariableAddress[o] :
|
||||
# 12| r0_7(glval<Is_A>) = VariableAddress[obj] :
|
||||
# 12| mu0_8(Object) = Store : &:r0_6, r0_7
|
||||
# 13| r0_9(glval<Object>) = VariableAddress[o] :
|
||||
# 13| r0_10(Object) = Load : &:r0_9, ~mu0_2
|
||||
# 13| r0_11(Is_A) = CheckedConvertOrNull : r0_10
|
||||
# 13| r0_12(Is_A) = Constant[0] :
|
||||
# 13| r0_13(Boolean) = CompareNE : r0_11, r0_12
|
||||
# 13| r0_14(Boolean) = ConditionalBranch : r0_13
|
||||
# 8| v0_0(Void) = EnterFunction :
|
||||
# 8| mu0_1(null) = AliasedDefinition :
|
||||
# 8| mu0_2(null) = UnmodeledDefinition :
|
||||
# 10| r0_3(glval<Is_A>) = VariableAddress[obj] :
|
||||
# 10| r0_4(null) = Constant[null] :
|
||||
# 10| r0_5(Is_A) = Convert : r0_4
|
||||
# 10| mu0_6(Is_A) = Store : &:r0_3, r0_4
|
||||
# 12| r0_7(glval<Object>) = VariableAddress[o] :
|
||||
# 12| r0_8(glval<Is_A>) = VariableAddress[obj] :
|
||||
# 12| r0_9(Object) = Convert : r0_8
|
||||
# 12| mu0_10(Object) = Store : &:r0_7, r0_8
|
||||
# 13| r0_11(glval<Object>) = VariableAddress[o] :
|
||||
# 13| r0_12(Object) = Load : &:r0_11, ~mu0_2
|
||||
# 13| r0_13(Is_A) = CheckedConvertOrNull : r0_12
|
||||
# 13| r0_14(Is_A) = Constant[0] :
|
||||
# 13| r0_15(Boolean) = CompareNE : r0_13, r0_14
|
||||
# 13| r0_16(Boolean) = ConditionalBranch : r0_15
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 3
|
||||
|
||||
@@ -571,13 +617,13 @@ isexpr.cs:
|
||||
# 8| v1_2(Void) = ExitFunction :
|
||||
|
||||
# 13| Block 2
|
||||
# 13| v2_0(Void) = ConditionalBranch : r0_13
|
||||
# 13| v2_0(Void) = ConditionalBranch : r0_15
|
||||
#-----| False -> Block 5
|
||||
#-----| True -> Block 4
|
||||
|
||||
# 13| Block 3
|
||||
# 13| r3_0(glval<Is_A>) = VariableAddress[tmp] :
|
||||
# 13| mu3_1(Is_A) = Store : &:r3_0, r0_11
|
||||
# 13| mu3_1(Is_A) = Store : &:r3_0, r0_13
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 15| Block 4
|
||||
@@ -603,6 +649,180 @@ isexpr.cs:
|
||||
# 18| v6_0(Void) = NoOp :
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
jumps.cs:
|
||||
# 5| System.Void Jumps.Main()
|
||||
# 5| Block 0
|
||||
# 5| v0_0(Void) = EnterFunction :
|
||||
# 5| mu0_1(null) = AliasedDefinition :
|
||||
# 5| mu0_2(null) = UnmodeledDefinition :
|
||||
# 7| r0_3(glval<Int32>) = VariableAddress[i] :
|
||||
# 7| r0_4(Int32) = Constant[1] :
|
||||
# 7| mu0_5(Int32) = Store : &:r0_3, r0_4
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 7| Block 1
|
||||
# 7| r1_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 7| r1_1(Int32) = Load : &:r1_0, ~mu0_2
|
||||
# 7| r1_2(Int32) = Constant[10] :
|
||||
# 7| r1_3(Boolean) = CompareLE : r1_1, r1_2
|
||||
# 7| v1_4(Void) = ConditionalBranch : r1_3
|
||||
#-----| False -> Block 7
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 9| Block 2
|
||||
# 9| r2_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 9| r2_1(Int32) = Load : &:r2_0, ~mu0_2
|
||||
# 9| r2_2(Int32) = Constant[3] :
|
||||
# 9| r2_3(Boolean) = CompareEQ : r2_1, r2_2
|
||||
# 9| v2_4(Void) = ConditionalBranch : r2_3
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
|
||||
# 10| Block 3
|
||||
# 10| v3_0(Void) = NoOp :
|
||||
#-----| Goto -> Block 19
|
||||
|
||||
# 11| Block 4
|
||||
# 11| r4_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 11| r4_1(Int32) = Load : &:r4_0, ~mu0_2
|
||||
# 11| r4_2(Int32) = Constant[5] :
|
||||
# 11| r4_3(Boolean) = CompareEQ : r4_1, r4_2
|
||||
# 11| v4_4(Void) = ConditionalBranch : r4_3
|
||||
#-----| False -> Block 6
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 12| Block 5
|
||||
# 12| v5_0(Void) = NoOp :
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 13| Block 6
|
||||
# 13| r6_0(glval<null>) = FunctionAddress[WriteLine] :
|
||||
# 13| r6_1(String) = StringConstant["BreakAndContinue"] :
|
||||
# 13| v6_2(Void) = Call : func:r6_0, 0:r6_1
|
||||
# 13| mu6_3(null) = ^CallSideEffect : ~mu0_2
|
||||
#-----| Goto -> Block 19
|
||||
|
||||
# 16| Block 7
|
||||
# 16| r7_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 16| r7_1(Int32) = Constant[0] :
|
||||
# 16| mu7_2(Int32) = Store : &:r7_0, r7_1
|
||||
#-----| Goto -> Block 8
|
||||
|
||||
# 16| Block 8
|
||||
# 16| r8_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 16| r8_1(Int32) = Load : &:r8_0, ~mu0_2
|
||||
# 16| r8_2(Int32) = Constant[10] :
|
||||
# 16| r8_3(Boolean) = CompareLT : r8_1, r8_2
|
||||
# 16| v8_4(Void) = ConditionalBranch : r8_3
|
||||
#-----| False -> Block 10
|
||||
#-----| True -> Block 9
|
||||
|
||||
# 18| Block 9
|
||||
# 18| r9_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 18| r9_1(Int32) = Load : &:r9_0, ~mu0_2
|
||||
# 18| r9_2(Int32) = Constant[1] :
|
||||
# 18| r9_3(Int32) = Add : r9_1, r9_2
|
||||
# 18| mu9_4(Int32) = Store : &:r9_0, r9_3
|
||||
# 19| v9_5(Void) = NoOp :
|
||||
#-----| Goto (back edge) -> Block 8
|
||||
|
||||
# 22| Block 10
|
||||
# 22| r10_0(glval<Int32>) = VariableAddress[a] :
|
||||
# 22| r10_1(Int32) = Constant[0] :
|
||||
# 22| mu10_2(Int32) = Store : &:r10_0, r10_1
|
||||
#-----| Goto -> Block 11
|
||||
|
||||
# 23| Block 11
|
||||
# 23| r11_0(Boolean) = Constant[true] :
|
||||
# 23| v11_1(Void) = ConditionalBranch : r11_0
|
||||
#-----| False -> Block 16
|
||||
#-----| True -> Block 12
|
||||
|
||||
# 25| Block 12
|
||||
# 25| r12_0(glval<Int32>) = VariableAddress[a] :
|
||||
# 25| r12_1(Int32) = Load : &:r12_0, ~mu0_2
|
||||
# 25| r12_2(Int32) = Constant[1] :
|
||||
# 25| r12_3(Int32) = Add : r12_1, r12_2
|
||||
# 25| mu12_4(Int32) = Store : &:r12_0, r12_3
|
||||
# 26| r12_5(glval<Int32>) = VariableAddress[a] :
|
||||
# 26| r12_6(Int32) = Load : &:r12_5, ~mu0_2
|
||||
# 26| r12_7(Int32) = Constant[5] :
|
||||
# 26| r12_8(Boolean) = CompareEQ : r12_6, r12_7
|
||||
# 26| v12_9(Void) = ConditionalBranch : r12_8
|
||||
#-----| False -> Block 14
|
||||
#-----| True -> Block 13
|
||||
|
||||
# 27| Block 13
|
||||
# 27| v13_0(Void) = NoOp :
|
||||
#-----| Goto (back edge) -> Block 11
|
||||
|
||||
# 28| Block 14
|
||||
# 28| r14_0(glval<Int32>) = VariableAddress[a] :
|
||||
# 28| r14_1(Int32) = Load : &:r14_0, ~mu0_2
|
||||
# 28| r14_2(Int32) = Constant[10] :
|
||||
# 28| r14_3(Boolean) = CompareEQ : r14_1, r14_2
|
||||
# 28| v14_4(Void) = ConditionalBranch : r14_3
|
||||
#-----| False (back edge) -> Block 11
|
||||
#-----| True -> Block 15
|
||||
|
||||
# 29| Block 15
|
||||
# 29| v15_0(Void) = NoOp :
|
||||
#-----| Goto -> Block 16
|
||||
|
||||
# 32| Block 16
|
||||
# 32| r16_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 32| r16_1(Int32) = Constant[1] :
|
||||
# 32| mu16_2(Int32) = Store : &:r16_0, r16_1
|
||||
#-----| Goto -> Block 18
|
||||
|
||||
# 32| Block 17
|
||||
# 32| r17_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 32| r17_1(Int32) = Load : &:r17_0, ~mu0_2
|
||||
# 32| r17_2(Int32) = Constant[1] :
|
||||
# 32| r17_3(Int32) = Add : r17_1, r17_2
|
||||
# 32| mu17_4(Int32) = Store : &:r17_0, r17_3
|
||||
#-----| Goto (back edge) -> Block 18
|
||||
|
||||
# 32| Block 18
|
||||
# 32| r18_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 32| r18_1(Int32) = Load : &:r18_0, ~mu0_2
|
||||
# 32| r18_2(Int32) = Constant[10] :
|
||||
# 32| r18_3(Boolean) = CompareLE : r18_1, r18_2
|
||||
# 32| v18_4(Void) = ConditionalBranch : r18_3
|
||||
#-----| False -> Block 22
|
||||
#-----| True -> Block 20
|
||||
|
||||
# 7| Block 19
|
||||
# 7| r19_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 7| r19_1(Int32) = Load : &:r19_0, ~mu0_2
|
||||
# 7| r19_2(Int32) = Constant[1] :
|
||||
# 7| r19_3(Int32) = Add : r19_1, r19_2
|
||||
# 7| mu19_4(Int32) = Store : &:r19_0, r19_3
|
||||
#-----| Goto (back edge) -> Block 1
|
||||
|
||||
# 34| Block 20
|
||||
# 34| r20_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 34| r20_1(Int32) = Load : &:r20_0, ~mu0_2
|
||||
# 34| r20_2(Int32) = Constant[5] :
|
||||
# 34| r20_3(Boolean) = CompareEQ : r20_1, r20_2
|
||||
# 34| v20_4(Void) = ConditionalBranch : r20_3
|
||||
#-----| False -> Block 17
|
||||
#-----| True -> Block 21
|
||||
|
||||
# 35| Block 21
|
||||
# 35| v21_0(Void) = NoOp :
|
||||
#-----| Goto -> Block 22
|
||||
|
||||
# 37| Block 22
|
||||
# 37| v22_0(Void) = NoOp :
|
||||
# 38| r22_1(glval<null>) = FunctionAddress[WriteLine] :
|
||||
# 38| r22_2(String) = StringConstant["Done"] :
|
||||
# 38| v22_3(Void) = Call : func:r22_1, 0:r22_2
|
||||
# 38| mu22_4(null) = ^CallSideEffect : ~mu0_2
|
||||
# 5| v22_5(Void) = ReturnVoid :
|
||||
# 5| v22_6(Void) = UnmodeledUse : mu*
|
||||
# 5| v22_7(Void) = ExitFunction :
|
||||
|
||||
lock.cs:
|
||||
# 5| System.Void LockTest.A()
|
||||
# 5| Block 0
|
||||
@@ -684,36 +904,56 @@ obj_creation.cs:
|
||||
# 11| v0_12(Void) = UnmodeledUse : mu*
|
||||
# 11| v0_13(Void) = ExitFunction :
|
||||
|
||||
# 17| System.Void ObjCreation.Main()
|
||||
# 17| System.Void ObjCreation.SomeFun(ObjCreation.MyClass)
|
||||
# 17| Block 0
|
||||
# 17| v0_0(Void) = EnterFunction :
|
||||
# 17| mu0_1(null) = AliasedDefinition :
|
||||
# 17| mu0_2(null) = UnmodeledDefinition :
|
||||
# 19| r0_3(glval<MyClass>) = VariableAddress[obj] :
|
||||
# 19| r0_4(MyClass) = NewObj :
|
||||
# 19| r0_5(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 19| r0_6(Int32) = Constant[100] :
|
||||
# 19| v0_7(Void) = Call : func:r0_5, this:r0_4, 0:r0_6
|
||||
# 19| mu0_8(null) = ^CallSideEffect : ~mu0_2
|
||||
# 19| mu0_9(MyClass) = Store : &:r0_3, r0_4
|
||||
# 20| r0_10(glval<MyClass>) = VariableAddress[obj_initlist] :
|
||||
# 20| r0_11(MyClass) = NewObj :
|
||||
# 20| r0_12(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 20| v0_13(Void) = Call : func:r0_12, this:r0_11
|
||||
# 20| mu0_14(null) = ^CallSideEffect : ~mu0_2
|
||||
# 20| r0_15(Int32) = Constant[101] :
|
||||
# 20| r0_16(glval<Int32>) = FieldAddress[x] : r0_11
|
||||
# 20| mu0_17(Int32) = Store : &:r0_16, r0_15
|
||||
# 20| mu0_18(MyClass) = Store : &:r0_10, r0_11
|
||||
# 21| r0_19(glval<Int32>) = VariableAddress[a] :
|
||||
# 21| r0_20(glval<MyClass>) = VariableAddress[obj] :
|
||||
# 21| r0_21(MyClass) = Load : &:r0_20, ~mu0_2
|
||||
# 21| r0_22(glval<Int32>) = FieldAddress[x] : r0_21
|
||||
# 21| r0_23(Int32) = Load : &:r0_22, ~mu0_2
|
||||
# 21| mu0_24(Int32) = Store : &:r0_19, r0_23
|
||||
# 17| v0_25(Void) = ReturnVoid :
|
||||
# 17| v0_26(Void) = UnmodeledUse : mu*
|
||||
# 17| v0_27(Void) = ExitFunction :
|
||||
# 17| v0_0(Void) = EnterFunction :
|
||||
# 17| mu0_1(null) = AliasedDefinition :
|
||||
# 17| mu0_2(null) = UnmodeledDefinition :
|
||||
# 17| r0_3(glval<MyClass>) = VariableAddress[x] :
|
||||
# 17| mu0_4(MyClass) = InitializeParameter[x] : &:r0_3
|
||||
# 18| v0_5(Void) = NoOp :
|
||||
# 17| v0_6(Void) = ReturnVoid :
|
||||
# 17| v0_7(Void) = UnmodeledUse : mu*
|
||||
# 17| v0_8(Void) = ExitFunction :
|
||||
|
||||
# 21| System.Void ObjCreation.Main()
|
||||
# 21| Block 0
|
||||
# 21| v0_0(Void) = EnterFunction :
|
||||
# 21| mu0_1(null) = AliasedDefinition :
|
||||
# 21| mu0_2(null) = UnmodeledDefinition :
|
||||
# 23| r0_3(glval<MyClass>) = VariableAddress[obj] :
|
||||
# 23| r0_4(MyClass) = NewObj :
|
||||
# 23| r0_5(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 23| r0_6(Int32) = Constant[100] :
|
||||
# 23| v0_7(Void) = Call : func:r0_5, this:r0_4, 0:r0_6
|
||||
# 23| mu0_8(null) = ^CallSideEffect : ~mu0_2
|
||||
# 23| mu0_9(MyClass) = Store : &:r0_3, r0_4
|
||||
# 24| r0_10(glval<MyClass>) = VariableAddress[obj_initlist] :
|
||||
# 24| r0_11(MyClass) = NewObj :
|
||||
# 24| r0_12(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 24| v0_13(Void) = Call : func:r0_12, this:r0_11
|
||||
# 24| mu0_14(null) = ^CallSideEffect : ~mu0_2
|
||||
# 24| r0_15(Int32) = Constant[101] :
|
||||
# 24| r0_16(glval<Int32>) = FieldAddress[x] : r0_11
|
||||
# 24| mu0_17(Int32) = Store : &:r0_16, r0_15
|
||||
# 24| mu0_18(MyClass) = Store : &:r0_10, r0_11
|
||||
# 25| r0_19(glval<Int32>) = VariableAddress[a] :
|
||||
# 25| r0_20(glval<MyClass>) = VariableAddress[obj] :
|
||||
# 25| r0_21(MyClass) = Load : &:r0_20, ~mu0_2
|
||||
# 25| r0_22(glval<Int32>) = FieldAddress[x] : r0_21
|
||||
# 25| r0_23(Int32) = Load : &:r0_22, ~mu0_2
|
||||
# 25| mu0_24(Int32) = Store : &:r0_19, r0_23
|
||||
# 27| r0_25(glval<null>) = FunctionAddress[SomeFun] :
|
||||
# 27| r0_26(MyClass) = NewObj :
|
||||
# 27| r0_27(glval<null>) = FunctionAddress[MyClass] :
|
||||
# 27| r0_28(Int32) = Constant[100] :
|
||||
# 27| v0_29(Void) = Call : func:r0_27, this:r0_26, 0:r0_28
|
||||
# 27| mu0_30(null) = ^CallSideEffect : ~mu0_2
|
||||
# 27| v0_31(Void) = Call : func:r0_25, 0:r0_26
|
||||
# 27| mu0_32(null) = ^CallSideEffect : ~mu0_2
|
||||
# 21| v0_33(Void) = ReturnVoid :
|
||||
# 21| v0_34(Void) = UnmodeledUse : mu*
|
||||
# 21| v0_35(Void) = ExitFunction :
|
||||
|
||||
prop.cs:
|
||||
# 7| System.Int32 PropClass.get_Prop()
|
||||
@@ -1048,6 +1288,9 @@ stmts.cs:
|
||||
# 71| r0_6(glval<Int32>) = VariableAddress[i] :
|
||||
# 71| r0_7(Int32) = Constant[0] :
|
||||
# 71| mu0_8(Int32) = Store : &:r0_6, r0_7
|
||||
# 71| r0_9(glval<Int32>) = VariableAddress[j] :
|
||||
# 71| r0_10(Int32) = Constant[10] :
|
||||
# 71| mu0_11(Int32) = Store : &:r0_9, r0_10
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 68| Block 1
|
||||
@@ -1058,53 +1301,92 @@ stmts.cs:
|
||||
# 71| Block 2
|
||||
# 71| r2_0(glval<Int32>) = VariableAddress[i] :
|
||||
# 71| r2_1(Int32) = Load : &:r2_0, ~mu0_2
|
||||
# 71| r2_2(Int32) = Constant[10] :
|
||||
# 71| r2_3(Boolean) = CompareLE : r2_1, r2_2
|
||||
# 71| v2_4(Void) = ConditionalBranch : r2_3
|
||||
#-----| False -> Block 1
|
||||
# 71| r2_2(glval<Int32>) = VariableAddress[j] :
|
||||
# 71| r2_3(Int32) = Load : &:r2_2, ~mu0_2
|
||||
# 71| r2_4(Boolean) = CompareLT : r2_1, r2_3
|
||||
# 71| v2_5(Void) = ConditionalBranch : r2_4
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
|
||||
# 73| Block 3
|
||||
# 73| r3_0(glval<Int32>) = VariableAddress[x] :
|
||||
# 73| r3_1(Int32) = Load : &:r3_0, ~mu0_2
|
||||
# 73| r3_2(Int32) = Constant[1] :
|
||||
# 73| r3_3(Int32) = Sub : r3_1, r3_2
|
||||
# 73| r3_4(glval<Int32>) = VariableAddress[x] :
|
||||
# 73| mu3_5(Int32) = Store : &:r3_4, r3_3
|
||||
# 71| r3_6(glval<Int32>) = VariableAddress[i] :
|
||||
# 71| r3_7(Int32) = Load : &:r3_6, ~mu0_2
|
||||
# 71| r3_8(Int32) = Constant[1] :
|
||||
# 71| r3_9(Int32) = Add : r3_7, r3_8
|
||||
# 71| mu3_10(Int32) = Store : &:r3_6, r3_9
|
||||
# 73| r3_0(glval<Int32>) = VariableAddress[x] :
|
||||
# 73| r3_1(Int32) = Load : &:r3_0, ~mu0_2
|
||||
# 73| r3_2(Int32) = Constant[1] :
|
||||
# 73| r3_3(Int32) = Sub : r3_1, r3_2
|
||||
# 73| r3_4(glval<Int32>) = VariableAddress[x] :
|
||||
# 73| mu3_5(Int32) = Store : &:r3_4, r3_3
|
||||
# 71| r3_6(glval<Int32>) = VariableAddress[i] :
|
||||
# 71| r3_7(Int32) = Load : &:r3_6, ~mu0_2
|
||||
# 71| r3_8(Int32) = Constant[1] :
|
||||
# 71| r3_9(Int32) = Add : r3_7, r3_8
|
||||
# 71| mu3_10(Int32) = Store : &:r3_6, r3_9
|
||||
# 71| r3_11(glval<Int32>) = VariableAddress[j] :
|
||||
# 71| r3_12(Int32) = Load : &:r3_11, ~mu0_2
|
||||
# 71| r3_13(Int32) = Constant[1] :
|
||||
# 71| r3_14(Int32) = Sub : r3_12, r3_13
|
||||
# 71| mu3_15(Int32) = Store : &:r3_11, r3_14
|
||||
#-----| Goto (back edge) -> Block 2
|
||||
|
||||
# 77| System.Void test_stmts.doWhile()
|
||||
# 77| Block 0
|
||||
# 77| v0_0(Void) = EnterFunction :
|
||||
# 77| mu0_1(null) = AliasedDefinition :
|
||||
# 77| mu0_2(null) = UnmodeledDefinition :
|
||||
# 79| r0_3(glval<Int32>) = VariableAddress[x] :
|
||||
# 79| r0_4(Int32) = Constant[0] :
|
||||
# 79| mu0_5(Int32) = Store : &:r0_3, r0_4
|
||||
# 76| Block 4
|
||||
# 76| r4_0(glval<Int32>) = VariableAddress[a] :
|
||||
# 76| mu4_1(Int32) = Uninitialized[a] : &:r4_0
|
||||
# 76| r4_2(glval<Int32>) = VariableAddress[b] :
|
||||
# 76| r4_3(Int32) = Constant[10] :
|
||||
# 76| mu4_4(Int32) = Store : &:r4_2, r4_3
|
||||
# 77| r4_5(Int32) = Constant[0] :
|
||||
# 77| r4_6(glval<Int32>) = VariableAddress[a] :
|
||||
# 77| mu4_7(Int32) = Store : &:r4_6, r4_5
|
||||
#-----| Goto -> Block 5
|
||||
|
||||
# 77| Block 5
|
||||
# 77| r5_0(glval<Int32>) = VariableAddress[a] :
|
||||
# 77| r5_1(Int32) = Load : &:r5_0, ~mu0_2
|
||||
# 77| r5_2(glval<Int32>) = VariableAddress[b] :
|
||||
# 77| r5_3(Int32) = Load : &:r5_2, ~mu0_2
|
||||
# 77| r5_4(Boolean) = CompareLT : r5_1, r5_3
|
||||
# 77| v5_5(Void) = ConditionalBranch : r5_4
|
||||
#-----| False -> Block 7
|
||||
#-----| True -> Block 6
|
||||
|
||||
# 79| Block 6
|
||||
# 79| r6_0(glval<Int32>) = VariableAddress[a] :
|
||||
# 79| r6_1(Int32) = Load : &:r6_0, ~mu0_2
|
||||
# 79| r6_2(Int32) = Constant[1] :
|
||||
# 79| r6_3(Int32) = Add : r6_1, r6_2
|
||||
# 79| mu6_4(Int32) = Store : &:r6_0, r6_3
|
||||
#-----| Goto (back edge) -> Block 5
|
||||
|
||||
# 83| Block 7
|
||||
# 83| v7_0(Void) = NoOp :
|
||||
#-----| Goto (back edge) -> Block 7
|
||||
|
||||
# 88| System.Void test_stmts.doWhile()
|
||||
# 88| Block 0
|
||||
# 88| v0_0(Void) = EnterFunction :
|
||||
# 88| mu0_1(null) = AliasedDefinition :
|
||||
# 88| mu0_2(null) = UnmodeledDefinition :
|
||||
# 90| r0_3(glval<Int32>) = VariableAddress[x] :
|
||||
# 90| r0_4(Int32) = Constant[0] :
|
||||
# 90| mu0_5(Int32) = Store : &:r0_3, r0_4
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 77| Block 1
|
||||
# 77| v1_0(Void) = ReturnVoid :
|
||||
# 77| v1_1(Void) = UnmodeledUse : mu*
|
||||
# 77| v1_2(Void) = ExitFunction :
|
||||
# 88| Block 1
|
||||
# 88| v1_0(Void) = ReturnVoid :
|
||||
# 88| v1_1(Void) = UnmodeledUse : mu*
|
||||
# 88| v1_2(Void) = ExitFunction :
|
||||
|
||||
# 82| Block 2
|
||||
# 82| r2_0(glval<Int32>) = VariableAddress[x] :
|
||||
# 82| r2_1(Int32) = Load : &:r2_0, ~mu0_2
|
||||
# 82| r2_2(Int32) = Constant[1] :
|
||||
# 82| r2_3(Int32) = Add : r2_1, r2_2
|
||||
# 82| r2_4(glval<Int32>) = VariableAddress[x] :
|
||||
# 82| mu2_5(Int32) = Store : &:r2_4, r2_3
|
||||
# 84| r2_6(glval<Int32>) = VariableAddress[x] :
|
||||
# 84| r2_7(Int32) = Load : &:r2_6, ~mu0_2
|
||||
# 84| r2_8(Int32) = Constant[10] :
|
||||
# 84| r2_9(Boolean) = CompareLT : r2_7, r2_8
|
||||
# 84| v2_10(Void) = ConditionalBranch : r2_9
|
||||
# 93| Block 2
|
||||
# 93| r2_0(glval<Int32>) = VariableAddress[x] :
|
||||
# 93| r2_1(Int32) = Load : &:r2_0, ~mu0_2
|
||||
# 93| r2_2(Int32) = Constant[1] :
|
||||
# 93| r2_3(Int32) = Add : r2_1, r2_2
|
||||
# 93| r2_4(glval<Int32>) = VariableAddress[x] :
|
||||
# 93| mu2_5(Int32) = Store : &:r2_4, r2_3
|
||||
# 95| r2_6(glval<Int32>) = VariableAddress[x] :
|
||||
# 95| r2_7(Int32) = Load : &:r2_6, ~mu0_2
|
||||
# 95| r2_8(Int32) = Constant[10] :
|
||||
# 95| r2_9(Boolean) = CompareLT : r2_7, r2_8
|
||||
# 95| v2_10(Void) = ConditionalBranch : r2_9
|
||||
#-----| False -> Block 1
|
||||
#-----| True (back edge) -> Block 2
|
||||
|
||||
|
||||
@@ -68,9 +68,20 @@ public class test_stmts
|
||||
public static void forStmt()
|
||||
{
|
||||
int x = 0;
|
||||
for (int i = 0; i <= 10; i++)
|
||||
for (int i = 0, j = 10; i < j; i++, j--)
|
||||
{
|
||||
x = x - 1;
|
||||
}
|
||||
|
||||
int a, b = 10;
|
||||
for (a = 0; a < b; )
|
||||
{
|
||||
x = x - 1;
|
||||
a++;
|
||||
}
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| Program.cs:62:17:62:35 | nameof(...) | Program.cs:62:24:62:34 | access to method MethodGroup |
|
||||
| Program.cs:63:13:63:50 | nameof(...) | Program.cs:63:20:63:49 | access to method MethodGroup |
|
||||
| Program.cs:169:16:169:29 | nameof(...) | Program.cs:169:23:169:28 | access to namespace System |
|
||||
| Program.cs:169:33:169:62 | nameof(...) | Program.cs:169:40:169:61 | access to namespace Tasks |
|
||||
|
||||
@@ -166,7 +166,7 @@ unsafe class ArrayTypesTest
|
||||
|
||||
class NameofNamespace
|
||||
{
|
||||
string s = nameof(System);
|
||||
string s = nameof(System) + nameof(System.Threading.Tasks);
|
||||
}
|
||||
|
||||
class UsingDiscard
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user