Merge branch 'main' into bring-back-type-barriers-in-non-constant-format

This commit is contained in:
Mathias Vorreiter Pedersen
2024-03-13 22:46:35 +00:00
277 changed files with 16870 additions and 30188 deletions

View File

@@ -0,0 +1,13 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
from Expr expr, int kind, int kind_new, Location loc
where
exprs(expr, kind, loc) and
if kind = 363 then kind_new = 1 else kind_new = kind
select expr, kind_new, loc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Introduce re-use expressions
compatibility: partial
expr_reuse.rel: delete
exprs.rel: run exprs.qlo

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -1322,3 +1322,23 @@ class CoYieldExpr extends UnaryOperation, @co_yield {
override int getPrecedence() { result = 2 }
}
/**
* An expression representing the re-use of another expression.
*
* In some specific cases an expression may be referred to outside its
* original context. A re-use expression wraps any such reference. A
* re-use expression can for example occur as the qualifier of an implicit
* destructor called on a temporary object, where the original use of the
* expression is in the definition of the temporary.
*/
class ReuseExpr extends Expr, @reuseexpr {
override string getAPrimaryQlClass() { result = "ReuseExpr" }
override string toString() { result = "reuse of " + this.getReusedExpr().toString() }
/**
* Gets the expression that is being re-used.
*/
Expr getReusedExpr() { expr_reuse(underlyingElement(this), unresolveElement(result)) }
}

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -285,6 +285,8 @@ deprecated private module Config implements FullStateConfigSig {
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
int accessPathLimit() { result = 5 }
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate sourceGrouping(Node source, string sourceGroup) {

View File

@@ -36,7 +36,9 @@ private class MallocAllocationFunction extends AllocationFunction {
"CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line)
"CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line)
"CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line)
"CRYPTO_secure_zalloc" // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
"CRYPTO_secure_zalloc", // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
"g_malloc", // g_malloc (n_bytes);
"g_try_malloc" // g_try_malloc(n_bytes);
]) and
sizeArg = 0
or
@@ -139,7 +141,9 @@ private class ReallocAllocationFunction extends AllocationFunction, TaintFunctio
// --- Windows COM allocation
"CoTaskMemRealloc", // CoTaskMemRealloc(ptr, size)
// --- OpenSSL memory allocation
"CRYPTO_realloc" // CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
"CRYPTO_realloc", // CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
"g_realloc", // g_realloc(mem, n_bytes);
"g_try_realloc" // g_try_realloc(mem, n_bytes);
]) and
sizeArg = 1 and
reallocArg = 0

View File

@@ -20,8 +20,10 @@ private class StandardDeallocationFunction extends DeallocationFunction {
freedArg = 0
or
this.hasGlobalName([
// --- OpenSSL memory allocation
"CRYPTO_free", "CRYPTO_secure_free"
// --- OpenSSL memory deallocation
"CRYPTO_free", "CRYPTO_secure_free",
// --- glib memory deallocation
"g_free"
]) and
freedArg = 0
or

View File

@@ -1513,6 +1513,11 @@ exprs(
int location: @location_expr ref
);
expr_reuse(
int reuse: @expr ref,
int original: @expr ref
)
/*
case @value.category of
1 = prval
@@ -1741,6 +1746,7 @@ case @expr.kind of
| 360 = @isunsigned
| 361 = @isvoid
| 362 = @isvolatile
| 363 = @reuseexpr
;
@var_args_expr = @vastartexpr

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Introduce re-use expressions
compatibility: backwards

View File

@@ -0,0 +1,50 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Certain casts in C and C++ place no restrictions on the target type. For
example, C style casts such as <code>(MyClass*)p</code> allows the programmer
to cast any pointer <code>p</code> to an expression of type <code>MyClass*</code>.
If the runtime type of <code>p</code> turns out to be a type that's incompatible
with <code>MyClass</code>, this results in undefined behavior.
</p>
</overview>
<recommendation>
<p>
If possible, use <code>dynamic_cast</code> to safely cast between polymorphic types.
If <code>dynamic_cast</code> is not an option, use <code>static_cast</code> to restrict
the kinds of conversions that the compiler is allowed to perform. If C++ style casts is
not an option, carefully check that all casts are safe.
</p>
</recommendation>
<example>
<p>
Consider the following class hierachy where we define a base class <code>Shape</code> and two
derived classes <code>Circle</code> and <code>Square</code> that are mutually incompatible:
</p>
<sample src="TypeConfusionCommon.cpp"/>
<p>
The following code demonstrates a type confusion vulnerability where the programmer
assumes that the runtime type of <code>p</code> is always a <code>Square</code>.
However, if <code>p</code> is a <code>Circle</code>, the cast will result in undefined behavior.
</p>
<sample src="TypeConfusionBad.cpp"/>
<p>
The following code fixes the vulnerability by using <code>dynamic_cast</code> to
safely cast between polymorphic types. If the cast fails, <code>dynamic_cast</code>
returns a null pointer, which can be checked for and handled appropriately.
</p>
<sample src="TypeConfusionGood.cpp"/>
</example>
<references>
<li>
Microsoft Learn: <a href="https://learn.microsoft.com/en-us/cpp/cpp/type-conversions-and-type-safety-modern-cpp">Type conversions and type safety</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,263 @@
/**
* @name Type confusion
* @description Casting a value to an incompatible type can lead to undefined behavior.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision medium
* @id cpp/type-confusion
* @tags security
* external/cwe/cwe-843
*/
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import Flow::PathGraph
/**
* Holds if `f` is a field located at byte offset `offset` in `c`.
*
* Note that predicate is recursive, so that given the following:
* ```cpp
* struct S1 {
* int a;
* void* b;
* };
*
* struct S2 {
* S1 s1;
* char c;
* };
* ```
* both `hasAFieldWithOffset(S2, s1, 0)` and `hasAFieldWithOffset(S2, a, 0)`
* holds.
*/
predicate hasAFieldWithOffset(Class c, Field f, int offset) {
// Base case: `f` is a field in `c`.
f = c.getAField() and
offset = f.getByteOffset() and
not f.getUnspecifiedType().(Class).hasDefinition()
or
// Otherwise, we find the struct that is a field of `c` which then has
// the field `f` as a member.
exists(Field g |
g = c.getAField() and
// Find the field with the largest offset that's less than or equal to
// offset. That's the struct we need to search recursively.
g =
max(Field cand, int candOffset |
cand = c.getAField() and
candOffset = cand.getByteOffset() and
offset >= candOffset
|
cand order by candOffset
) and
hasAFieldWithOffset(g.getUnspecifiedType(), f, offset - g.getByteOffset())
)
}
/** Holds if `f` is the last field of its declaring class. */
predicate lastField(Field f) {
exists(Class c | c = f.getDeclaringType() |
f =
max(Field cand, int byteOffset |
cand.getDeclaringType() = c and byteOffset = f.getByteOffset()
|
cand order by byteOffset
)
)
}
/**
* Holds if there exists a field in `c2` at offset `offset` that's compatible
* with `f1`.
*/
bindingset[f1, offset, c2]
pragma[inline_late]
predicate hasCompatibleFieldAtOffset(Field f1, int offset, Class c2) {
exists(Field f2 | hasAFieldWithOffset(c2, f2, offset) |
// Let's not deal with bit-fields for now.
f2 instanceof BitField
or
f1.getUnspecifiedType().getSize() = f2.getUnspecifiedType().getSize()
or
lastField(f1) and
f1.getUnspecifiedType().getSize() <= f2.getUnspecifiedType().getSize()
)
}
/**
* Holds if `c1` is a prefix of `c2`.
*/
bindingset[c1, c2]
pragma[inline_late]
predicate prefix(Class c1, Class c2) {
not c1.isPolymorphic() and
not c2.isPolymorphic() and
if c1 instanceof Union
then
// If it's a union we just verify that one of it's variants is compatible with the other class
exists(Field f1, int offset |
// Let's not deal with bit-fields for now.
not f1 instanceof BitField and
hasAFieldWithOffset(c1, f1, offset)
|
hasCompatibleFieldAtOffset(f1, offset, c2)
)
else
forall(Field f1, int offset |
// Let's not deal with bit-fields for now.
not f1 instanceof BitField and
hasAFieldWithOffset(c1, f1, offset)
|
hasCompatibleFieldAtOffset(f1, offset, c2)
)
}
/**
* An unsafe cast is any explicit cast that is not
* a `dynamic_cast`.
*/
class UnsafeCast extends Cast {
private Class toType;
UnsafeCast() {
(
this instanceof CStyleCast
or
this instanceof StaticCast
or
this instanceof ReinterpretCast
) and
toType = this.getExplicitlyConverted().getUnspecifiedType().stripType() and
not this.isImplicit() and
exists(TypeDeclarationEntry tde |
tde = toType.getDefinition() and
not tde.isFromUninstantiatedTemplate(_)
)
}
Class getConvertedType() { result = toType }
/**
* Holds if the result of this cast can safely be interpreted as a value of
* type `t`.
*
* The compatibility rules are as follows:
*
* 1. the result of `(T)x` is compatible with the type `T` for any `T`
* 2. the result of `(T)x` is compatible with the type `U` for any `U` such
* that `U` is a subtype of `T`, or `T` is a subtype of `U`.
* 3. the result of `(T)x` is compatible with the type `U` if the list
* of fields of `T` is a prefix of the list of fields of `U`.
* For example, if `U` is `struct { unsigned char x; int y; };`
* and `T` is `struct { unsigned char uc; };`.
* 4. the result of `(T)x` is compatible with the type `U` if the list
* of fields of `U` is a prefix of the list of fields of `T`.
*
* Condition 4 is a bit controversial, since it assumes that the additional
* fields in `T` won't be accessed. This may result in some FNs.
*/
bindingset[this, t]
pragma[inline_late]
predicate compatibleWith(Type t) {
// Conition 1
t.stripType() = this.getConvertedType()
or
// Condition 3
prefix(this.getConvertedType(), t.stripType())
or
// Condition 4
prefix(t.stripType(), this.getConvertedType())
or
// Condition 2 (a)
t.stripType().(Class).getABaseClass+() = this.getConvertedType()
or
// Condition 2 (b)
t.stripType() = this.getConvertedType().getABaseClass+()
}
}
/**
* Holds if `source` is an allocation that allocates a value of type `type`.
*/
predicate isSourceImpl(DataFlow::Node source, Class type) {
exists(AllocationExpr alloc |
alloc = source.asExpr() and
type = alloc.getAllocatedElementType().stripType() and
not exists(
alloc
.(NewOrNewArrayExpr)
.getAllocator()
.(OperatorNewAllocationFunction)
.getPlacementArgument()
)
) and
exists(TypeDeclarationEntry tde |
tde = type.getDefinition() and
not tde.isFromUninstantiatedTemplate(_)
)
}
/** A configuration describing flow from an allocation to a potentially unsafe cast. */
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
predicate isBarrier(DataFlow::Node node) {
// We disable flow through global variables to reduce FPs from infeasible paths
node instanceof DataFlow::VariableNode
or
exists(Class c | c = node.getType().stripType() |
not c.hasDefinition()
or
exists(TypeDeclarationEntry tde |
tde = c.getDefinition() and
tde.isFromUninstantiatedTemplate(_)
)
)
}
predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(UnsafeCast cast).getUnconverted() }
int fieldFlowBranchLimit() { result = 0 }
}
module Flow = DataFlow::Global<Config>;
predicate relevantType(DataFlow::Node sink, Class allocatedType) {
exists(DataFlow::Node source |
Flow::flow(source, sink) and
isSourceImpl(source, allocatedType)
)
}
predicate isSinkImpl(
DataFlow::Node sink, Class allocatedType, Type convertedType, boolean compatible
) {
exists(UnsafeCast cast |
relevantType(sink, allocatedType) and
sink.asExpr() = cast.getUnconverted() and
convertedType = cast.getConvertedType()
|
if cast.compatibleWith(allocatedType) then compatible = true else compatible = false
)
}
from
Flow::PathNode source, Flow::PathNode sink, Type badSourceType, Type sinkType,
DataFlow::Node sinkNode
where
Flow::flowPath(source, sink) and
sinkNode = sink.getNode() and
isSourceImpl(source.getNode(), badSourceType) and
isSinkImpl(sinkNode, badSourceType, sinkType, false) and
// If there is any flow that would result in a valid cast then we don't
// report an alert here. This reduces the number of FPs from infeasible paths
// significantly.
not exists(DataFlow::Node goodSource, Type goodSourceType |
isSourceImpl(goodSource, goodSourceType) and
isSinkImpl(sinkNode, goodSourceType, sinkType, true) and
Flow::flow(goodSource, sinkNode)
)
select sinkNode, source, sink, "Conversion from $@ to $@ is invalid.", badSourceType,
badSourceType.toString(), sinkType, sinkType.toString()

View File

@@ -0,0 +1,7 @@
void allocate_and_draw_bad() {
Shape* shape = new Circle;
// ...
// BAD: Assumes that shape is always a Square
Square* square = static_cast<Square*>(shape);
int length = square->getLength();
}

View File

@@ -0,0 +1,25 @@
struct Shape {
virtual ~Shape();
virtual void draw() = 0;
};
struct Circle : public Shape {
Circle();
void draw() override {
/* ... */
}
int getRadius();
};
struct Square : public Shape {
Square();
void draw() override {
/* ... */
}
int getLength();
};

View File

@@ -0,0 +1,11 @@
void allocate_and_draw_good() {
Shape* shape = new Circle;
// ...
// GOOD: Dynamically checks if shape is a Square
Square* square = dynamic_cast<Square*>(shape);
if(square) {
int length = square->getLength();
} else {
// handle error
}
}

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query, `cpp/type-confusion`, to detect casts to invalid types.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added models for `GLib` allocation and deallocation functions.

View File

@@ -1728,6 +1728,374 @@ complex.c:
# 144| Type = [LongDoubleType] long double
# 144| ValueCategory = prvalue
# 145| getStmt(72): [ReturnStmt] return ...
destructors_for_temps.cpp:
# 1| [CopyAssignmentOperator] ClassWithDestructor2& ClassWithDestructor2::operator=(ClassWithDestructor2 const&)
# 1| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const ClassWithDestructor2 &
# 1| [CopyConstructor] void ClassWithDestructor2::ClassWithDestructor2(ClassWithDestructor2 const&)
# 1| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const ClassWithDestructor2 &
# 3| [Constructor] void ClassWithDestructor2::ClassWithDestructor2()
# 3| <params>:
# 4| [Destructor] void ClassWithDestructor2::~ClassWithDestructor2()
# 4| <params>:
# 6| [MemberFunction] char ClassWithDestructor2::get_x()
# 6| <params>:
# 9| [CopyAssignmentOperator] ClassWithConstructor& ClassWithConstructor::operator=(ClassWithConstructor const&)
# 9| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const ClassWithConstructor &
# 9| [MoveAssignmentOperator] ClassWithConstructor& ClassWithConstructor::operator=(ClassWithConstructor&&)
# 9| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] ClassWithConstructor &&
# 9| [CopyConstructor] void ClassWithConstructor::ClassWithConstructor(ClassWithConstructor const&)
# 9| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const ClassWithConstructor &
# 9| [MoveConstructor] void ClassWithConstructor::ClassWithConstructor(ClassWithConstructor&&)
# 9| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] ClassWithConstructor &&
# 9| <initializations>:
# 9| getEntryPoint(): [BlockStmt] { ... }
# 9| getStmt(0): [ReturnStmt] return ...
# 11| [Constructor] void ClassWithConstructor::ClassWithConstructor(char, char)
# 11| <params>:
# 11| getParameter(0): [Parameter] x
# 11| Type = [PlainCharType] char
# 11| getParameter(1): [Parameter] y
# 11| Type = [PlainCharType] char
# 14| [TopLevelFunction] char temp_test()
# 14| <params>:
# 14| getEntryPoint(): [BlockStmt] { ... }
# 15| getStmt(0): [DeclStmt] declaration
# 15| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 15| Type = [PlainCharType] char
# 15| getVariable().getInitializer(): [Initializer] initializer for x
# 15| getExpr(): [FunctionCall] call to get_x
# 15| Type = [PlainCharType] char
# 15| ValueCategory = prvalue
# 15| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 15| Type = [VoidType] void
# 15| ValueCategory = prvalue
# 15| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 15| Type = [Class] ClassWithDestructor2
# 15| ValueCategory = prvalue(load)
# 16| getStmt(1): [DeclStmt] declaration
# 16| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 16| Type = [Class] ClassWithConstructor
# 16| getVariable().getInitializer(): [Initializer] initializer for y
# 16| getExpr(): [ConstructorCall] call to ClassWithConstructor
# 16| Type = [VoidType] void
# 16| ValueCategory = prvalue
# 16| getArgument(0): [CharLiteral] 97
# 16| Type = [PlainCharType] char
# 16| Value = [CharLiteral] 97
# 16| ValueCategory = prvalue
# 16| getArgument(1): [FunctionCall] call to get_x
# 16| Type = [PlainCharType] char
# 16| ValueCategory = prvalue
# 16| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 16| Type = [VoidType] void
# 16| ValueCategory = prvalue
# 16| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 16| Type = [Class] ClassWithDestructor2
# 16| ValueCategory = prvalue(load)
# 17| getStmt(2): [ReturnStmt] return ...
# 17| getExpr(): [FunctionCall] call to get_x
# 17| Type = [PlainCharType] char
# 17| ValueCategory = prvalue
# 17| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 17| Type = [VoidType] void
# 17| ValueCategory = prvalue
# 17| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 17| Type = [Class] ClassWithDestructor2
# 17| ValueCategory = prvalue(load)
# 21| [TopLevelFunction] char temp_test2()
# 21| <params>:
# 21| getEntryPoint(): [BlockStmt] { ... }
# 22| getStmt(0): [ExprStmt] ExprStmt
# 22| getExpr(): [NewExpr] new
# 22| Type = [PointerType] ClassWithDestructor2 *
# 22| ValueCategory = prvalue
# 22| getInitializer(): [ConstructorCall] call to ClassWithDestructor2
# 22| Type = [VoidType] void
# 22| ValueCategory = prvalue
# 23| getStmt(1): [ReturnStmt] return ...
# 23| getExpr(): [AddExpr] ... + ...
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getLeftOperand(): [FunctionCall] call to get_x
# 23| Type = [PlainCharType] char
# 23| ValueCategory = prvalue
# 23| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 23| Type = [Class] ClassWithDestructor2
# 23| ValueCategory = prvalue(load)
# 23| getRightOperand(): [FunctionCall] call to get_x
# 23| Type = [PlainCharType] char
# 23| ValueCategory = prvalue
# 23| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 23| Type = [Class] ClassWithDestructor2
# 23| ValueCategory = prvalue(load)
# 23| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
# 23| Conversion = [IntegralConversion] integral conversion
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getRightOperand().getFullyConverted(): [CStyleCast] (int)...
# 23| Conversion = [IntegralConversion] integral conversion
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue
# 23| getExpr().getFullyConverted(): [CStyleCast] (char)...
# 23| Conversion = [IntegralConversion] integral conversion
# 23| Type = [PlainCharType] char
# 23| ValueCategory = prvalue
# 27| [FunctionTemplateInstantiation,TopLevelFunction] ClassWithDestructor2 returnValue<ClassWithDestructor2>()
# 27| <params>:
# 27| [TemplateFunction,TopLevelFunction] T returnValue<T>()
# 27| <params>:
# 29| [TopLevelFunction] void temp_test3()
# 29| <params>:
# 29| getEntryPoint(): [BlockStmt] { ... }
# 30| getStmt(0): [DeclStmt] declaration
# 30| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rs
# 30| Type = [LValueReferenceType] const ClassWithDestructor2 &
# 30| getVariable().getInitializer(): [Initializer] initializer for rs
# 30| getExpr(): [FunctionCall] call to returnValue
# 30| Type = [Class] ClassWithDestructor2
# 30| ValueCategory = prvalue
# 30| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 30| Type = [LValueReferenceType] const ClassWithDestructor2 &
# 30| ValueCategory = prvalue
# 30| getExpr(): [CStyleCast] (const ClassWithDestructor2)...
# 30| Conversion = [GlvalueConversion] glvalue conversion
# 30| Type = [SpecifiedType] const ClassWithDestructor2
# 30| ValueCategory = lvalue
# 30| getExpr(): [TemporaryObjectExpr] temporary object
# 30| Type = [Class] ClassWithDestructor2
# 30| ValueCategory = lvalue
# 31| getStmt(1): [ReturnStmt] return ...
# 33| [TopLevelFunction] void temp_test4()
# 33| <params>:
# 33| getEntryPoint(): [BlockStmt] { ... }
# 34| getStmt(0): [DeclStmt] declaration
# 34| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 34| Type = [Class] ClassWithDestructor2
# 34| getVariable().getInitializer(): [Initializer] initializer for c
# 34| getExpr(): [ConstructorCall] call to ClassWithDestructor2
# 34| Type = [VoidType] void
# 34| ValueCategory = prvalue
# 35| getStmt(1): [DeclStmt] declaration
# 35| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rs2
# 35| Type = [LValueReferenceType] const ClassWithDestructor2 &
# 35| getVariable().getInitializer(): [Initializer] initializer for rs2
# 35| getExpr(): [FunctionCall] call to returnValue
# 35| Type = [Class] ClassWithDestructor2
# 35| ValueCategory = prvalue
# 35| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 35| Type = [LValueReferenceType] const ClassWithDestructor2 &
# 35| ValueCategory = prvalue
# 35| getExpr(): [CStyleCast] (const ClassWithDestructor2)...
# 35| Conversion = [GlvalueConversion] glvalue conversion
# 35| Type = [SpecifiedType] const ClassWithDestructor2
# 35| ValueCategory = lvalue
# 35| getExpr(): [TemporaryObjectExpr] temporary object
# 35| Type = [Class] ClassWithDestructor2
# 35| ValueCategory = lvalue
# 36| getStmt(2): [ReturnStmt] return ...
# 36| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2
# 36| Type = [VoidType] void
# 36| ValueCategory = prvalue
# 36| getQualifier(): [VariableAccess] c
# 36| Type = [Class] ClassWithDestructor2
# 36| ValueCategory = lvalue
# 38| [TopLevelFunction] void temp_test5(bool)
# 38| <params>:
# 38| getParameter(0): [Parameter] b
# 38| Type = [BoolType] bool
# 38| getEntryPoint(): [BlockStmt] { ... }
# 39| getStmt(0): [ExprStmt] ExprStmt
# 39| getExpr(): [ConditionalExpr] ... ? ... : ...
# 39| Type = [Class] ClassWithDestructor2
# 39| ValueCategory = prvalue
# 39| getCondition(): [VariableAccess] b
# 39| Type = [BoolType] bool
# 39| ValueCategory = prvalue(load)
# 39| getThen(): [ConstructorCall] call to ClassWithDestructor2
# 39| Type = [VoidType] void
# 39| ValueCategory = prvalue
# 39| getElse(): [ConstructorCall] call to ClassWithDestructor2
# 39| Type = [VoidType] void
# 39| ValueCategory = prvalue
# 39| getThen().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 39| Type = [Class] ClassWithDestructor2
# 39| ValueCategory = prvalue(load)
# 39| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 39| Type = [Class] ClassWithDestructor2
# 39| ValueCategory = prvalue(load)
# 39| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 39| Type = [Class] ClassWithDestructor2
# 39| ValueCategory = prvalue
# 40| getStmt(1): [ReturnStmt] return ...
# 42| [TopLevelFunction] void temp_test6(bool)
# 42| <params>:
# 42| getParameter(0): [Parameter] b
# 42| Type = [BoolType] bool
# 42| getEntryPoint(): [BlockStmt] { ... }
# 43| getStmt(0): [DeclStmt] declaration
# 43| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 43| Type = [Class] ClassWithDestructor2
# 43| getVariable().getInitializer(): [Initializer] initializer for c
# 43| getExpr(): [ConstructorCall] call to ClassWithDestructor2
# 43| Type = [VoidType] void
# 43| ValueCategory = prvalue
# 44| getStmt(1): [IfStmt] if (...) ...
# 44| getCondition(): [VariableAccess] b
# 44| Type = [BoolType] bool
# 44| ValueCategory = prvalue(load)
# 44| getThen(): [BlockStmt] { ... }
# 45| getStmt(0): [ExprStmt] ExprStmt
# 45| getExpr(): [ThrowExpr] throw ...
# 45| Type = [Class] ClassWithConstructor
# 45| ValueCategory = prvalue
# 45| getExpr(): [ConstructorCall] call to ClassWithConstructor
# 45| Type = [VoidType] void
# 45| ValueCategory = prvalue
# 45| getArgument(0): [CharLiteral] 120
# 45| Type = [PlainCharType] char
# 45| Value = [CharLiteral] 120
# 45| ValueCategory = prvalue
# 45| getArgument(1): [FunctionCall] call to get_x
# 45| Type = [PlainCharType] char
# 45| ValueCategory = prvalue
# 45| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 45| Type = [VoidType] void
# 45| ValueCategory = prvalue
# 45| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 45| Type = [Class] ClassWithDestructor2
# 45| ValueCategory = prvalue(load)
# 47| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2
# 47| Type = [VoidType] void
# 47| ValueCategory = prvalue
# 47| getQualifier(): [VariableAccess] c
# 47| Type = [Class] ClassWithDestructor2
# 47| ValueCategory = lvalue
# 47| getStmt(2): [ReturnStmt] return ...
# 47| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2
# 47| Type = [VoidType] void
# 47| ValueCategory = prvalue
# 47| getQualifier(): [VariableAccess] c
# 47| Type = [Class] ClassWithDestructor2
# 47| ValueCategory = lvalue
# 49| [TopLevelFunction] void temp_test7(bool)
# 49| <params>:
# 49| getParameter(0): [Parameter] b
# 49| Type = [BoolType] bool
# 49| getEntryPoint(): [BlockStmt] { ... }
# 50| getStmt(0): [DeclStmt] declaration
# 50| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 50| Type = [Class] ClassWithDestructor2
# 50| getVariable().getInitializer(): [Initializer] initializer for c
# 50| getExpr(): [ConstructorCall] call to ClassWithDestructor2
# 50| Type = [VoidType] void
# 50| ValueCategory = prvalue
# 51| getStmt(1): [ExprStmt] ExprStmt
# 51| getExpr(): [ConditionalExpr] ... ? ... : ...
# 51| Type = [Class] ClassWithDestructor2
# 51| ValueCategory = prvalue(load)
# 51| getCondition(): [VariableAccess] b
# 51| Type = [BoolType] bool
# 51| ValueCategory = prvalue(load)
# 51| getThen(): [ThrowExpr] throw ...
# 51| Type = [Class] ClassWithConstructor
# 51| ValueCategory = prvalue
# 51| getExpr(): [ConstructorCall] call to ClassWithConstructor
# 51| Type = [VoidType] void
# 51| ValueCategory = prvalue
# 51| getArgument(0): [CharLiteral] 120
# 51| Type = [PlainCharType] char
# 51| Value = [CharLiteral] 120
# 51| ValueCategory = prvalue
# 51| getArgument(1): [FunctionCall] call to get_x
# 51| Type = [PlainCharType] char
# 51| ValueCategory = prvalue
# 51| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 51| Type = [VoidType] void
# 51| ValueCategory = prvalue
# 51| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 51| Type = [Class] ClassWithDestructor2
# 51| ValueCategory = prvalue(load)
# 52| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2
# 52| Type = [VoidType] void
# 52| ValueCategory = prvalue
# 52| getQualifier(): [VariableAccess] c
# 52| Type = [Class] ClassWithDestructor2
# 52| ValueCategory = lvalue
# 51| getElse(): [ConstructorCall] call to ClassWithDestructor2
# 51| Type = [VoidType] void
# 51| ValueCategory = prvalue
# 51| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 51| Type = [Class] ClassWithDestructor2
# 51| ValueCategory = prvalue(load)
# 51| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 51| Type = [Class] ClassWithDestructor2
# 51| ValueCategory = prvalue
# 52| getStmt(2): [ReturnStmt] return ...
# 52| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2
# 52| Type = [VoidType] void
# 52| ValueCategory = prvalue
# 52| getQualifier(): [VariableAccess] c
# 52| Type = [Class] ClassWithDestructor2
# 52| ValueCategory = lvalue
# 54| [TopLevelFunction] void temp_test8(bool)
# 54| <params>:
# 54| getParameter(0): [Parameter] b
# 54| Type = [BoolType] bool
# 54| getEntryPoint(): [BlockStmt] { ... }
# 55| getStmt(0): [ExprStmt] ExprStmt
# 55| getExpr(): [ConditionalExpr] ... ? ... : ...
# 55| Type = [Class] ClassWithDestructor2
# 55| ValueCategory = prvalue(load)
# 55| getCondition(): [VariableAccess] b
# 55| Type = [BoolType] bool
# 55| ValueCategory = prvalue(load)
# 55| getThen(): [ThrowExpr] throw ...
# 55| Type = [Class] ClassWithConstructor
# 55| ValueCategory = prvalue
# 55| getExpr(): [ConstructorCall] call to ClassWithConstructor
# 55| Type = [VoidType] void
# 55| ValueCategory = prvalue
# 55| getArgument(0): [CharLiteral] 120
# 55| Type = [PlainCharType] char
# 55| Value = [CharLiteral] 120
# 55| ValueCategory = prvalue
# 55| getArgument(1): [FunctionCall] call to get_x
# 55| Type = [PlainCharType] char
# 55| ValueCategory = prvalue
# 55| getQualifier(): [ConstructorCall] call to ClassWithDestructor2
# 55| Type = [VoidType] void
# 55| ValueCategory = prvalue
# 55| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 55| Type = [Class] ClassWithDestructor2
# 55| ValueCategory = prvalue(load)
# 55| getElse(): [ConstructorCall] call to ClassWithDestructor2
# 55| Type = [VoidType] void
# 55| ValueCategory = prvalue
# 55| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 55| Type = [Class] ClassWithDestructor2
# 55| ValueCategory = prvalue(load)
# 55| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object
# 55| Type = [Class] ClassWithDestructor2
# 55| ValueCategory = prvalue
# 56| getStmt(1): [ReturnStmt] return ...
ir.c:
# 5| [TopLevelFunction] int getX(MyCoords*)
# 5| <params>:

View File

@@ -738,6 +738,499 @@ complex.c:
# 58| v58_6(void) = AliasedUse : m58_3
# 58| v58_7(void) = ExitFunction :
destructors_for_temps.cpp:
# 9| void ClassWithConstructor::ClassWithConstructor(ClassWithConstructor&&)
# 9| Block 0
# 9| v9_1(void) = EnterFunction :
# 9| m9_2(unknown) = AliasedDefinition :
# 9| m9_3(unknown) = InitializeNonLocal :
# 9| m9_4(unknown) = Chi : total:m9_2, partial:m9_3
# 9| r9_5(glval<unknown>) = VariableAddress[#this] :
# 9| m9_6(glval<ClassWithConstructor>) = InitializeParameter[#this] : &:r9_5
# 9| r9_7(glval<ClassWithConstructor>) = Load[#this] : &:r9_5, m9_6
# 9| m9_8(ClassWithConstructor) = InitializeIndirection[#this] : &:r9_7
#-----| r0_1(glval<ClassWithConstructor &&>) = VariableAddress[(unnamed parameter 0)] :
#-----| m0_2(ClassWithConstructor &&) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
#-----| r0_3(ClassWithConstructor &&) = Load[(unnamed parameter 0)] : &:r0_1, m0_2
#-----| m0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
# 9| v9_9(void) = NoOp :
# 9| v9_10(void) = ReturnIndirection[#this] : &:r9_7, m9_8
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, m0_4
# 9| v9_11(void) = ReturnVoid :
# 9| v9_12(void) = AliasedUse : m9_3
# 9| v9_13(void) = ExitFunction :
# 14| char temp_test()
# 14| Block 0
# 14| v14_1(void) = EnterFunction :
# 14| m14_2(unknown) = AliasedDefinition :
# 14| m14_3(unknown) = InitializeNonLocal :
# 14| m14_4(unknown) = Chi : total:m14_2, partial:m14_3
# 15| r15_1(glval<char>) = VariableAddress[x] :
# 15| r15_2(glval<ClassWithDestructor2>) = VariableAddress[#temp15:14] :
# 15| m15_3(ClassWithDestructor2) = Uninitialized[#temp15:14] : &:r15_2
# 15| r15_4(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 15| v15_5(void) = Call[ClassWithDestructor2] : func:r15_4, this:r15_2
# 15| m15_6(unknown) = ^CallSideEffect : ~m14_4
# 15| m15_7(unknown) = Chi : total:m14_4, partial:m15_6
# 15| m15_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r15_2
# 15| m15_9(ClassWithDestructor2) = Chi : total:m15_3, partial:m15_8
# 15| r15_10(glval<unknown>) = FunctionAddress[get_x] :
# 15| r15_11(char) = Call[get_x] : func:r15_10, this:r15_2
# 15| m15_12(unknown) = ^CallSideEffect : ~m15_7
# 15| m15_13(unknown) = Chi : total:m15_7, partial:m15_12
# 15| v15_14(void) = ^IndirectReadSideEffect[-1] : &:r15_2, m15_9
# 15| m15_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r15_2
# 15| m15_16(ClassWithDestructor2) = Chi : total:m15_9, partial:m15_15
# 15| m15_17(char) = Store[x] : &:r15_1, r15_11
# 16| r16_1(glval<ClassWithConstructor>) = VariableAddress[y] :
# 16| m16_2(ClassWithConstructor) = Uninitialized[y] : &:r16_1
# 16| r16_3(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 16| r16_4(char) = Constant[97] :
# 16| r16_5(glval<ClassWithDestructor2>) = VariableAddress[#temp16:33] :
# 16| m16_6(ClassWithDestructor2) = Uninitialized[#temp16:33] : &:r16_5
# 16| r16_7(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 16| v16_8(void) = Call[ClassWithDestructor2] : func:r16_7, this:r16_5
# 16| m16_9(unknown) = ^CallSideEffect : ~m15_13
# 16| m16_10(unknown) = Chi : total:m15_13, partial:m16_9
# 16| m16_11(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r16_5
# 16| m16_12(ClassWithDestructor2) = Chi : total:m16_6, partial:m16_11
# 16| r16_13(glval<unknown>) = FunctionAddress[get_x] :
# 16| r16_14(char) = Call[get_x] : func:r16_13, this:r16_5
# 16| m16_15(unknown) = ^CallSideEffect : ~m16_10
# 16| m16_16(unknown) = Chi : total:m16_10, partial:m16_15
# 16| v16_17(void) = ^IndirectReadSideEffect[-1] : &:r16_5, m16_12
# 16| m16_18(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r16_5
# 16| m16_19(ClassWithDestructor2) = Chi : total:m16_12, partial:m16_18
# 16| v16_20(void) = Call[ClassWithConstructor] : func:r16_3, this:r16_1, 0:r16_4, 1:r16_14
# 16| m16_21(unknown) = ^CallSideEffect : ~m16_16
# 16| m16_22(unknown) = Chi : total:m16_16, partial:m16_21
# 16| m16_23(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r16_1
# 16| m16_24(ClassWithConstructor) = Chi : total:m16_2, partial:m16_23
# 17| r17_1(glval<char>) = VariableAddress[#return] :
# 17| r17_2(glval<ClassWithDestructor2>) = VariableAddress[#temp17:12] :
# 17| m17_3(ClassWithDestructor2) = Uninitialized[#temp17:12] : &:r17_2
# 17| r17_4(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 17| v17_5(void) = Call[ClassWithDestructor2] : func:r17_4, this:r17_2
# 17| m17_6(unknown) = ^CallSideEffect : ~m16_22
# 17| m17_7(unknown) = Chi : total:m16_22, partial:m17_6
# 17| m17_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r17_2
# 17| m17_9(ClassWithDestructor2) = Chi : total:m17_3, partial:m17_8
# 17| r17_10(glval<unknown>) = FunctionAddress[get_x] :
# 17| r17_11(char) = Call[get_x] : func:r17_10, this:r17_2
# 17| m17_12(unknown) = ^CallSideEffect : ~m17_7
# 17| m17_13(unknown) = Chi : total:m17_7, partial:m17_12
# 17| v17_14(void) = ^IndirectReadSideEffect[-1] : &:r17_2, m17_9
# 17| m17_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r17_2
# 17| m17_16(ClassWithDestructor2) = Chi : total:m17_9, partial:m17_15
# 17| m17_17(char) = Store[#return] : &:r17_1, r17_11
# 14| r14_5(glval<char>) = VariableAddress[#return] :
# 14| v14_6(void) = ReturnValue : &:r14_5, m17_17
# 14| v14_7(void) = AliasedUse : ~m17_13
# 14| v14_8(void) = ExitFunction :
# 21| char temp_test2()
# 21| Block 0
# 21| v21_1(void) = EnterFunction :
# 21| m21_2(unknown) = AliasedDefinition :
# 21| m21_3(unknown) = InitializeNonLocal :
# 21| m21_4(unknown) = Chi : total:m21_2, partial:m21_3
# 22| r22_1(glval<unknown>) = FunctionAddress[operator new] :
# 22| r22_2(unsigned long) = Constant[1] :
# 22| r22_3(void *) = Call[operator new] : func:r22_1, 0:r22_2
# 22| m22_4(unknown) = ^CallSideEffect : ~m21_4
# 22| m22_5(unknown) = Chi : total:m21_4, partial:m22_4
# 22| m22_6(unknown) = ^InitializeDynamicAllocation : &:r22_3
# 22| r22_7(ClassWithDestructor2 *) = Convert : r22_3
# 22| r22_8(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 22| v22_9(void) = Call[ClassWithDestructor2] : func:r22_8, this:r22_7
# 22| m22_10(unknown) = ^CallSideEffect : ~m22_5
# 22| m22_11(unknown) = Chi : total:m22_5, partial:m22_10
# 22| m22_12(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r22_7
# 22| m22_13(unknown) = Chi : total:m22_6, partial:m22_12
# 23| r23_1(glval<char>) = VariableAddress[#return] :
# 23| r23_2(glval<ClassWithDestructor2>) = VariableAddress[#temp23:12] :
# 23| m23_3(ClassWithDestructor2) = Uninitialized[#temp23:12] : &:r23_2
# 23| r23_4(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 23| v23_5(void) = Call[ClassWithDestructor2] : func:r23_4, this:r23_2
# 23| m23_6(unknown) = ^CallSideEffect : ~m22_11
# 23| m23_7(unknown) = Chi : total:m22_11, partial:m23_6
# 23| m23_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_2
# 23| m23_9(ClassWithDestructor2) = Chi : total:m23_3, partial:m23_8
# 23| r23_10(glval<unknown>) = FunctionAddress[get_x] :
# 23| r23_11(char) = Call[get_x] : func:r23_10, this:r23_2
# 23| m23_12(unknown) = ^CallSideEffect : ~m23_7
# 23| m23_13(unknown) = Chi : total:m23_7, partial:m23_12
# 23| v23_14(void) = ^IndirectReadSideEffect[-1] : &:r23_2, m23_9
# 23| m23_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_2
# 23| m23_16(ClassWithDestructor2) = Chi : total:m23_9, partial:m23_15
# 23| r23_17(int) = Convert : r23_11
# 23| r23_18(glval<ClassWithDestructor2>) = VariableAddress[#temp23:45] :
# 23| m23_19(ClassWithDestructor2) = Uninitialized[#temp23:45] : &:r23_18
# 23| r23_20(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 23| v23_21(void) = Call[ClassWithDestructor2] : func:r23_20, this:r23_18
# 23| m23_22(unknown) = ^CallSideEffect : ~m23_13
# 23| m23_23(unknown) = Chi : total:m23_13, partial:m23_22
# 23| m23_24(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_18
# 23| m23_25(ClassWithDestructor2) = Chi : total:m23_19, partial:m23_24
# 23| r23_26(glval<unknown>) = FunctionAddress[get_x] :
# 23| r23_27(char) = Call[get_x] : func:r23_26, this:r23_18
# 23| m23_28(unknown) = ^CallSideEffect : ~m23_23
# 23| m23_29(unknown) = Chi : total:m23_23, partial:m23_28
# 23| v23_30(void) = ^IndirectReadSideEffect[-1] : &:r23_18, m23_25
# 23| m23_31(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_18
# 23| m23_32(ClassWithDestructor2) = Chi : total:m23_25, partial:m23_31
# 23| r23_33(int) = Convert : r23_27
# 23| r23_34(int) = Add : r23_17, r23_33
# 23| r23_35(char) = Convert : r23_34
# 23| m23_36(char) = Store[#return] : &:r23_1, r23_35
# 21| r21_5(glval<char>) = VariableAddress[#return] :
# 21| v21_6(void) = ReturnValue : &:r21_5, m23_36
# 21| v21_7(void) = AliasedUse : ~m23_29
# 21| v21_8(void) = ExitFunction :
# 29| void temp_test3()
# 29| Block 0
# 29| v29_1(void) = EnterFunction :
# 29| m29_2(unknown) = AliasedDefinition :
# 29| m29_3(unknown) = InitializeNonLocal :
# 29| m29_4(unknown) = Chi : total:m29_2, partial:m29_3
# 30| r30_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs] :
# 30| r30_2(glval<ClassWithDestructor2>) = VariableAddress[#temp30:38] :
# 30| r30_3(glval<unknown>) = FunctionAddress[returnValue] :
# 30| r30_4(ClassWithDestructor2) = Call[returnValue] : func:r30_3
# 30| m30_5(unknown) = ^CallSideEffect : ~m29_4
# 30| m30_6(unknown) = Chi : total:m29_4, partial:m30_5
# 30| m30_7(ClassWithDestructor2) = Store[#temp30:38] : &:r30_2, r30_4
# 30| r30_8(glval<ClassWithDestructor2>) = Convert : r30_2
# 30| r30_9(ClassWithDestructor2 &) = CopyValue : r30_8
# 30| m30_10(ClassWithDestructor2 &) = Store[rs] : &:r30_1, r30_9
# 31| v31_1(void) = NoOp :
# 29| v29_5(void) = ReturnVoid :
# 29| v29_6(void) = AliasedUse : ~m30_6
# 29| v29_7(void) = ExitFunction :
# 33| void temp_test4()
# 33| Block 0
# 33| v33_1(void) = EnterFunction :
# 33| m33_2(unknown) = AliasedDefinition :
# 33| m33_3(unknown) = InitializeNonLocal :
# 33| m33_4(unknown) = Chi : total:m33_2, partial:m33_3
# 34| r34_1(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 34| m34_2(ClassWithDestructor2) = Uninitialized[c] : &:r34_1
# 34| r34_3(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 34| v34_4(void) = Call[ClassWithDestructor2] : func:r34_3, this:r34_1
# 34| m34_5(unknown) = ^CallSideEffect : ~m33_4
# 34| m34_6(unknown) = Chi : total:m33_4, partial:m34_5
# 34| m34_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r34_1
# 34| m34_8(ClassWithDestructor2) = Chi : total:m34_2, partial:m34_7
# 35| r35_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs2] :
# 35| r35_2(glval<ClassWithDestructor2>) = VariableAddress[#temp35:39] :
# 35| r35_3(glval<unknown>) = FunctionAddress[returnValue] :
# 35| r35_4(ClassWithDestructor2) = Call[returnValue] : func:r35_3
# 35| m35_5(unknown) = ^CallSideEffect : ~m34_6
# 35| m35_6(unknown) = Chi : total:m34_6, partial:m35_5
# 35| m35_7(ClassWithDestructor2) = Store[#temp35:39] : &:r35_2, r35_4
# 35| r35_8(glval<ClassWithDestructor2>) = Convert : r35_2
# 35| r35_9(ClassWithDestructor2 &) = CopyValue : r35_8
# 35| m35_10(ClassWithDestructor2 &) = Store[rs2] : &:r35_1, r35_9
# 36| v36_1(void) = NoOp :
# 36| r36_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 36| r36_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
# 36| v36_4(void) = Call[~ClassWithDestructor2] : func:r36_3, this:r36_2
# 36| m36_5(unknown) = ^CallSideEffect : ~m35_6
# 36| m36_6(unknown) = Chi : total:m35_6, partial:m36_5
# 36| v36_7(void) = ^IndirectReadSideEffect[-1] : &:r36_2, m34_8
# 36| m36_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r36_2
# 36| m36_9(ClassWithDestructor2) = Chi : total:m34_8, partial:m36_8
# 33| v33_5(void) = ReturnVoid :
# 33| v33_6(void) = AliasedUse : ~m36_6
# 33| v33_7(void) = ExitFunction :
# 38| void temp_test5(bool)
# 38| Block 0
# 38| v38_1(void) = EnterFunction :
# 38| m38_2(unknown) = AliasedDefinition :
# 38| m38_3(unknown) = InitializeNonLocal :
# 38| m38_4(unknown) = Chi : total:m38_2, partial:m38_3
# 38| r38_5(glval<bool>) = VariableAddress[b] :
# 38| m38_6(bool) = InitializeParameter[b] : &:r38_5
# 39| r39_1(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| r39_2(glval<bool>) = VariableAddress[b] :
# 39| r39_3(bool) = Load[b] : &:r39_2, m38_6
# 39| v39_4(void) = ConditionalBranch : r39_3
#-----| False -> Block 3
#-----| True -> Block 2
# 39| Block 1
# 39| m39_5(unknown) = Phi : from 2:~m39_15, from 3:~m39_26
# 39| m39_6(ClassWithDestructor2) = Phi : from 2:m39_20, from 3:m39_31
# 39| r39_7(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| r39_8(ClassWithDestructor2) = Load[#temp39:3] : &:r39_7, m39_6
# 39| m39_9(ClassWithDestructor2) = Store[#temp39:3] : &:r39_1, r39_8
# 40| v40_1(void) = NoOp :
# 38| v38_7(void) = ReturnVoid :
# 38| v38_8(void) = AliasedUse : ~m39_5
# 38| v38_9(void) = ExitFunction :
# 39| Block 2
# 39| r39_10(glval<ClassWithDestructor2>) = VariableAddress[#temp39:7] :
# 39| m39_11(ClassWithDestructor2) = Uninitialized[#temp39:7] : &:r39_10
# 39| r39_12(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 39| v39_13(void) = Call[ClassWithDestructor2] : func:r39_12, this:r39_10
# 39| m39_14(unknown) = ^CallSideEffect : ~m38_4
# 39| m39_15(unknown) = Chi : total:m38_4, partial:m39_14
# 39| m39_16(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r39_10
# 39| m39_17(ClassWithDestructor2) = Chi : total:m39_11, partial:m39_16
# 39| r39_18(ClassWithDestructor2) = Load[#temp39:7] : &:r39_10, m39_17
# 39| r39_19(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| m39_20(ClassWithDestructor2) = Store[#temp39:3] : &:r39_19, r39_18
#-----| Goto -> Block 1
# 39| Block 3
# 39| r39_21(glval<ClassWithDestructor2>) = VariableAddress[#temp39:32] :
# 39| m39_22(ClassWithDestructor2) = Uninitialized[#temp39:32] : &:r39_21
# 39| r39_23(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 39| v39_24(void) = Call[ClassWithDestructor2] : func:r39_23, this:r39_21
# 39| m39_25(unknown) = ^CallSideEffect : ~m38_4
# 39| m39_26(unknown) = Chi : total:m38_4, partial:m39_25
# 39| m39_27(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r39_21
# 39| m39_28(ClassWithDestructor2) = Chi : total:m39_22, partial:m39_27
# 39| r39_29(ClassWithDestructor2) = Load[#temp39:32] : &:r39_21, m39_28
# 39| r39_30(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| m39_31(ClassWithDestructor2) = Store[#temp39:3] : &:r39_30, r39_29
#-----| Goto -> Block 1
# 42| void temp_test6(bool)
# 42| Block 0
# 42| v42_1(void) = EnterFunction :
# 42| m42_2(unknown) = AliasedDefinition :
# 42| m42_3(unknown) = InitializeNonLocal :
# 42| m42_4(unknown) = Chi : total:m42_2, partial:m42_3
# 42| r42_5(glval<bool>) = VariableAddress[b] :
# 42| m42_6(bool) = InitializeParameter[b] : &:r42_5
# 43| r43_1(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 43| m43_2(ClassWithDestructor2) = Uninitialized[c] : &:r43_1
# 43| r43_3(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 43| v43_4(void) = Call[ClassWithDestructor2] : func:r43_3, this:r43_1
# 43| m43_5(unknown) = ^CallSideEffect : ~m42_4
# 43| m43_6(unknown) = Chi : total:m42_4, partial:m43_5
# 43| m43_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r43_1
# 43| m43_8(ClassWithDestructor2) = Chi : total:m43_2, partial:m43_7
# 44| r44_1(glval<bool>) = VariableAddress[b] :
# 44| r44_2(bool) = Load[b] : &:r44_1, m42_6
# 44| v44_3(void) = ConditionalBranch : r44_2
#-----| False -> Block 4
#-----| True -> Block 3
# 42| Block 1
# 42| m42_7(unknown) = Phi : from 2:~m45_22, from 4:~m47_6
# 42| v42_8(void) = AliasedUse : ~m42_7
# 42| v42_9(void) = ExitFunction :
# 42| Block 2
# 42| v42_10(void) = Unwind :
#-----| Goto -> Block 1
# 45| Block 3
# 45| r45_1(glval<ClassWithConstructor>) = VariableAddress[#throw45:7] :
# 45| m45_2(ClassWithConstructor) = Uninitialized[#throw45:7] : &:r45_1
# 45| r45_3(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 45| r45_4(char) = Constant[120] :
# 45| r45_5(glval<ClassWithDestructor2>) = VariableAddress[#temp45:39] :
# 45| m45_6(ClassWithDestructor2) = Uninitialized[#temp45:39] : &:r45_5
# 45| r45_7(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 45| v45_8(void) = Call[ClassWithDestructor2] : func:r45_7, this:r45_5
# 45| m45_9(unknown) = ^CallSideEffect : ~m43_6
# 45| m45_10(unknown) = Chi : total:m43_6, partial:m45_9
# 45| m45_11(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r45_5
# 45| m45_12(ClassWithDestructor2) = Chi : total:m45_6, partial:m45_11
# 45| r45_13(glval<unknown>) = FunctionAddress[get_x] :
# 45| r45_14(char) = Call[get_x] : func:r45_13, this:r45_5
# 45| m45_15(unknown) = ^CallSideEffect : ~m45_10
# 45| m45_16(unknown) = Chi : total:m45_10, partial:m45_15
# 45| v45_17(void) = ^IndirectReadSideEffect[-1] : &:r45_5, m45_12
# 45| m45_18(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r45_5
# 45| m45_19(ClassWithDestructor2) = Chi : total:m45_12, partial:m45_18
# 45| v45_20(void) = Call[ClassWithConstructor] : func:r45_3, this:r45_1, 0:r45_4, 1:r45_14
# 45| m45_21(unknown) = ^CallSideEffect : ~m45_16
# 45| m45_22(unknown) = Chi : total:m45_16, partial:m45_21
# 45| m45_23(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r45_1
# 45| m45_24(ClassWithConstructor) = Chi : total:m45_2, partial:m45_23
# 45| v45_25(void) = ThrowValue : &:r45_1, m45_24
#-----| Exception -> Block 2
# 47| Block 4
# 47| v47_1(void) = NoOp :
# 47| r47_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 47| r47_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
# 47| v47_4(void) = Call[~ClassWithDestructor2] : func:r47_3, this:r47_2
# 47| m47_5(unknown) = ^CallSideEffect : ~m43_6
# 47| m47_6(unknown) = Chi : total:m43_6, partial:m47_5
# 47| v47_7(void) = ^IndirectReadSideEffect[-1] : &:r47_2, m43_8
# 47| m47_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r47_2
# 47| m47_9(ClassWithDestructor2) = Chi : total:m43_8, partial:m47_8
# 42| v42_11(void) = ReturnVoid :
#-----| Goto -> Block 1
# 49| void temp_test7(bool)
# 49| Block 0
# 49| v49_1(void) = EnterFunction :
# 49| m49_2(unknown) = AliasedDefinition :
# 49| m49_3(unknown) = InitializeNonLocal :
# 49| m49_4(unknown) = Chi : total:m49_2, partial:m49_3
# 49| r49_5(glval<bool>) = VariableAddress[b] :
# 49| m49_6(bool) = InitializeParameter[b] : &:r49_5
# 50| r50_1(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 50| m50_2(ClassWithDestructor2) = Uninitialized[c] : &:r50_1
# 50| r50_3(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 50| v50_4(void) = Call[ClassWithDestructor2] : func:r50_3, this:r50_1
# 50| m50_5(unknown) = ^CallSideEffect : ~m49_4
# 50| m50_6(unknown) = Chi : total:m49_4, partial:m50_5
# 50| m50_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r50_1
# 50| m50_8(ClassWithDestructor2) = Chi : total:m50_2, partial:m50_7
# 51| r51_1(glval<ClassWithDestructor2>) = VariableAddress[#temp51:5] :
# 51| r51_2(glval<bool>) = VariableAddress[b] :
# 51| r51_3(bool) = Load[b] : &:r51_2, m49_6
# 51| v51_4(void) = ConditionalBranch : r51_3
#-----| False -> Block 4
#-----| True -> Block 3
# 49| Block 1
# 49| m49_7(unknown) = Phi : from 2:~m51_26, from 4:~m52_6
# 49| v49_8(void) = AliasedUse : ~m49_7
# 49| v49_9(void) = ExitFunction :
# 49| Block 2
# 49| v49_10(void) = Unwind :
#-----| Goto -> Block 1
# 51| Block 3
# 51| r51_5(glval<ClassWithConstructor>) = VariableAddress[#throw51:9] :
# 51| m51_6(ClassWithConstructor) = Uninitialized[#throw51:9] : &:r51_5
# 51| r51_7(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 51| r51_8(char) = Constant[120] :
# 51| r51_9(glval<ClassWithDestructor2>) = VariableAddress[#temp51:41] :
# 51| m51_10(ClassWithDestructor2) = Uninitialized[#temp51:41] : &:r51_9
# 51| r51_11(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 51| v51_12(void) = Call[ClassWithDestructor2] : func:r51_11, this:r51_9
# 51| m51_13(unknown) = ^CallSideEffect : ~m50_6
# 51| m51_14(unknown) = Chi : total:m50_6, partial:m51_13
# 51| m51_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r51_9
# 51| m51_16(ClassWithDestructor2) = Chi : total:m51_10, partial:m51_15
# 51| r51_17(glval<unknown>) = FunctionAddress[get_x] :
# 51| r51_18(char) = Call[get_x] : func:r51_17, this:r51_9
# 51| m51_19(unknown) = ^CallSideEffect : ~m51_14
# 51| m51_20(unknown) = Chi : total:m51_14, partial:m51_19
# 51| v51_21(void) = ^IndirectReadSideEffect[-1] : &:r51_9, m51_16
# 51| m51_22(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r51_9
# 51| m51_23(ClassWithDestructor2) = Chi : total:m51_16, partial:m51_22
# 51| v51_24(void) = Call[ClassWithConstructor] : func:r51_7, this:r51_5, 0:r51_8, 1:r51_18
# 51| m51_25(unknown) = ^CallSideEffect : ~m51_20
# 51| m51_26(unknown) = Chi : total:m51_20, partial:m51_25
# 51| m51_27(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r51_5
# 51| m51_28(ClassWithConstructor) = Chi : total:m51_6, partial:m51_27
# 51| v51_29(void) = ThrowValue : &:r51_5, m51_28
#-----| Exception -> Block 2
# 51| Block 4
# 51| r51_30(glval<ClassWithDestructor2>) = VariableAddress[#temp51:75] :
# 51| m51_31(ClassWithDestructor2) = Uninitialized[#temp51:75] : &:r51_30
# 51| r51_32(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 51| v51_33(void) = Call[ClassWithDestructor2] : func:r51_32, this:r51_30
# 51| m51_34(unknown) = ^CallSideEffect : ~m50_6
# 51| m51_35(unknown) = Chi : total:m50_6, partial:m51_34
# 51| m51_36(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r51_30
# 51| m51_37(ClassWithDestructor2) = Chi : total:m51_31, partial:m51_36
# 51| r51_38(ClassWithDestructor2) = Load[#temp51:75] : &:r51_30, m51_37
# 51| r51_39(glval<ClassWithDestructor2>) = VariableAddress[#temp51:5] :
# 51| m51_40(ClassWithDestructor2) = Store[#temp51:5] : &:r51_39, r51_38
# 51| r51_41(glval<ClassWithDestructor2>) = VariableAddress[#temp51:5] :
# 51| r51_42(ClassWithDestructor2) = Load[#temp51:5] : &:r51_41, m51_40
# 51| m51_43(ClassWithDestructor2) = Store[#temp51:5] : &:r51_1, r51_42
# 52| v52_1(void) = NoOp :
# 52| r52_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 52| r52_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
# 52| v52_4(void) = Call[~ClassWithDestructor2] : func:r52_3, this:r52_2
# 52| m52_5(unknown) = ^CallSideEffect : ~m51_35
# 52| m52_6(unknown) = Chi : total:m51_35, partial:m52_5
# 52| v52_7(void) = ^IndirectReadSideEffect[-1] : &:r52_2, m50_8
# 52| m52_8(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r52_2
# 52| m52_9(ClassWithDestructor2) = Chi : total:m50_8, partial:m52_8
# 49| v49_11(void) = ReturnVoid :
#-----| Goto -> Block 1
# 54| void temp_test8(bool)
# 54| Block 0
# 54| v54_1(void) = EnterFunction :
# 54| m54_2(unknown) = AliasedDefinition :
# 54| m54_3(unknown) = InitializeNonLocal :
# 54| m54_4(unknown) = Chi : total:m54_2, partial:m54_3
# 54| r54_5(glval<bool>) = VariableAddress[b] :
# 54| m54_6(bool) = InitializeParameter[b] : &:r54_5
# 55| r55_1(glval<ClassWithDestructor2>) = VariableAddress[#temp55:5] :
# 55| r55_2(glval<bool>) = VariableAddress[b] :
# 55| r55_3(bool) = Load[b] : &:r55_2, m54_6
# 55| v55_4(void) = ConditionalBranch : r55_3
#-----| False -> Block 4
#-----| True -> Block 3
# 54| Block 1
# 54| m54_7(unknown) = Phi : from 2:~m55_26, from 4:~m55_35
# 54| v54_8(void) = AliasedUse : ~m54_7
# 54| v54_9(void) = ExitFunction :
# 54| Block 2
# 54| v54_10(void) = Unwind :
#-----| Goto -> Block 1
# 55| Block 3
# 55| r55_5(glval<ClassWithConstructor>) = VariableAddress[#throw55:9] :
# 55| m55_6(ClassWithConstructor) = Uninitialized[#throw55:9] : &:r55_5
# 55| r55_7(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 55| r55_8(char) = Constant[120] :
# 55| r55_9(glval<ClassWithDestructor2>) = VariableAddress[#temp55:41] :
# 55| m55_10(ClassWithDestructor2) = Uninitialized[#temp55:41] : &:r55_9
# 55| r55_11(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 55| v55_12(void) = Call[ClassWithDestructor2] : func:r55_11, this:r55_9
# 55| m55_13(unknown) = ^CallSideEffect : ~m54_4
# 55| m55_14(unknown) = Chi : total:m54_4, partial:m55_13
# 55| m55_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r55_9
# 55| m55_16(ClassWithDestructor2) = Chi : total:m55_10, partial:m55_15
# 55| r55_17(glval<unknown>) = FunctionAddress[get_x] :
# 55| r55_18(char) = Call[get_x] : func:r55_17, this:r55_9
# 55| m55_19(unknown) = ^CallSideEffect : ~m55_14
# 55| m55_20(unknown) = Chi : total:m55_14, partial:m55_19
# 55| v55_21(void) = ^IndirectReadSideEffect[-1] : &:r55_9, m55_16
# 55| m55_22(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r55_9
# 55| m55_23(ClassWithDestructor2) = Chi : total:m55_16, partial:m55_22
# 55| v55_24(void) = Call[ClassWithConstructor] : func:r55_7, this:r55_5, 0:r55_8, 1:r55_18
# 55| m55_25(unknown) = ^CallSideEffect : ~m55_20
# 55| m55_26(unknown) = Chi : total:m55_20, partial:m55_25
# 55| m55_27(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r55_5
# 55| m55_28(ClassWithConstructor) = Chi : total:m55_6, partial:m55_27
# 55| v55_29(void) = ThrowValue : &:r55_5, m55_28
#-----| Exception -> Block 2
# 55| Block 4
# 55| r55_30(glval<ClassWithDestructor2>) = VariableAddress[#temp55:75] :
# 55| m55_31(ClassWithDestructor2) = Uninitialized[#temp55:75] : &:r55_30
# 55| r55_32(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 55| v55_33(void) = Call[ClassWithDestructor2] : func:r55_32, this:r55_30
# 55| m55_34(unknown) = ^CallSideEffect : ~m54_4
# 55| m55_35(unknown) = Chi : total:m54_4, partial:m55_34
# 55| m55_36(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r55_30
# 55| m55_37(ClassWithDestructor2) = Chi : total:m55_31, partial:m55_36
# 55| r55_38(ClassWithDestructor2) = Load[#temp55:75] : &:r55_30, m55_37
# 55| r55_39(glval<ClassWithDestructor2>) = VariableAddress[#temp55:5] :
# 55| m55_40(ClassWithDestructor2) = Store[#temp55:5] : &:r55_39, r55_38
# 55| r55_41(glval<ClassWithDestructor2>) = VariableAddress[#temp55:5] :
# 55| r55_42(ClassWithDestructor2) = Load[#temp55:5] : &:r55_41, m55_40
# 55| m55_43(ClassWithDestructor2) = Store[#temp55:5] : &:r55_1, r55_42
# 56| v56_1(void) = NoOp :
# 54| v54_11(void) = ReturnVoid :
#-----| Goto -> Block 1
ir.c:
# 7| void MyCoordsTest(int)
# 7| Block 0

View File

@@ -0,0 +1,56 @@
class ClassWithDestructor2 {
public:
ClassWithDestructor2();
~ClassWithDestructor2();
char get_x();
};
class ClassWithConstructor {
public:
ClassWithConstructor(char x, char y);
};
char temp_test() {
char x = ClassWithDestructor2().get_x();
ClassWithConstructor y('a', ClassWithDestructor2().get_x());
return ClassWithDestructor2().get_x();
}
char temp_test2() {
new ClassWithDestructor2();
return ClassWithDestructor2().get_x() + ClassWithDestructor2().get_x();
}
template<typename T>
T returnValue();
void temp_test3() {
const ClassWithDestructor2& rs = returnValue<ClassWithDestructor2>();
}
void temp_test4() {
ClassWithDestructor2 c;
const ClassWithDestructor2& rs2 = returnValue<ClassWithDestructor2>();
}
void temp_test5(bool b) {
b ? ClassWithDestructor2() : ClassWithDestructor2();
}
void temp_test6(bool b) {
ClassWithDestructor2 c;
if (b) {
throw ClassWithConstructor('x', ClassWithDestructor2().get_x());
}
}
void temp_test7(bool b) {
ClassWithDestructor2 c;
b ? throw ClassWithConstructor('x', ClassWithDestructor2().get_x()) : ClassWithDestructor2();
}
void temp_test8(bool b) {
b ? throw ClassWithConstructor('x', ClassWithDestructor2().get_x()) : ClassWithDestructor2();
}

View File

@@ -652,6 +652,440 @@
| complex.c:144:8:144:10 | Load | m133_5 |
| complex.c:144:8:144:10 | StoreValue | r144_3 |
| complex.c:144:8:144:10 | Unary | r144_2 |
| destructors_for_temps.cpp:9:7:9:7 | Address | &:r9_5 |
| destructors_for_temps.cpp:9:7:9:7 | Address | &:r9_5 |
| destructors_for_temps.cpp:9:7:9:7 | Address | &:r9_7 |
| destructors_for_temps.cpp:9:7:9:7 | Address | &:r9_7 |
| destructors_for_temps.cpp:9:7:9:7 | ChiPartial | partial:m9_3 |
| destructors_for_temps.cpp:9:7:9:7 | ChiTotal | total:m9_2 |
| destructors_for_temps.cpp:9:7:9:7 | Load | m9_6 |
| destructors_for_temps.cpp:9:7:9:7 | SideEffect | m9_3 |
| destructors_for_temps.cpp:9:7:9:7 | SideEffect | m9_8 |
| destructors_for_temps.cpp:14:6:14:14 | Address | &:r14_5 |
| destructors_for_temps.cpp:14:6:14:14 | ChiPartial | partial:m14_3 |
| destructors_for_temps.cpp:14:6:14:14 | ChiTotal | total:m14_2 |
| destructors_for_temps.cpp:14:6:14:14 | Load | m17_17 |
| destructors_for_temps.cpp:14:6:14:14 | SideEffect | ~m17_13 |
| destructors_for_temps.cpp:15:10:15:10 | Address | &:r15_1 |
| destructors_for_temps.cpp:15:14:15:35 | Address | &:r15_2 |
| destructors_for_temps.cpp:15:14:15:35 | Address | &:r15_2 |
| destructors_for_temps.cpp:15:14:15:35 | Address | &:r15_2 |
| destructors_for_temps.cpp:15:14:15:35 | Address | &:r15_2 |
| destructors_for_temps.cpp:15:14:15:35 | Arg(this) | this:r15_2 |
| destructors_for_temps.cpp:15:14:15:35 | Arg(this) | this:r15_2 |
| destructors_for_temps.cpp:15:14:15:35 | CallTarget | func:r15_4 |
| destructors_for_temps.cpp:15:14:15:35 | ChiPartial | partial:m15_6 |
| destructors_for_temps.cpp:15:14:15:35 | ChiPartial | partial:m15_8 |
| destructors_for_temps.cpp:15:14:15:35 | ChiPartial | partial:m15_15 |
| destructors_for_temps.cpp:15:14:15:35 | ChiTotal | total:m14_4 |
| destructors_for_temps.cpp:15:14:15:35 | ChiTotal | total:m15_3 |
| destructors_for_temps.cpp:15:14:15:35 | ChiTotal | total:m15_9 |
| destructors_for_temps.cpp:15:14:15:35 | SideEffect | m15_9 |
| destructors_for_temps.cpp:15:14:15:35 | SideEffect | ~m14_4 |
| destructors_for_temps.cpp:15:37:15:41 | CallTarget | func:r15_10 |
| destructors_for_temps.cpp:15:37:15:41 | ChiPartial | partial:m15_12 |
| destructors_for_temps.cpp:15:37:15:41 | ChiTotal | total:m15_7 |
| destructors_for_temps.cpp:15:37:15:41 | SideEffect | ~m15_7 |
| destructors_for_temps.cpp:15:37:15:41 | StoreValue | r15_11 |
| destructors_for_temps.cpp:16:26:16:26 | Address | &:r16_1 |
| destructors_for_temps.cpp:16:26:16:26 | Address | &:r16_1 |
| destructors_for_temps.cpp:16:26:16:26 | Arg(this) | this:r16_1 |
| destructors_for_temps.cpp:16:28:16:30 | Arg(0) | 0:r16_4 |
| destructors_for_temps.cpp:16:28:16:63 | CallTarget | func:r16_3 |
| destructors_for_temps.cpp:16:28:16:63 | ChiPartial | partial:m16_21 |
| destructors_for_temps.cpp:16:28:16:63 | ChiPartial | partial:m16_23 |
| destructors_for_temps.cpp:16:28:16:63 | ChiTotal | total:m16_2 |
| destructors_for_temps.cpp:16:28:16:63 | ChiTotal | total:m16_16 |
| destructors_for_temps.cpp:16:28:16:63 | SideEffect | ~m16_16 |
| destructors_for_temps.cpp:16:33:16:54 | Address | &:r16_5 |
| destructors_for_temps.cpp:16:33:16:54 | Address | &:r16_5 |
| destructors_for_temps.cpp:16:33:16:54 | Address | &:r16_5 |
| destructors_for_temps.cpp:16:33:16:54 | Address | &:r16_5 |
| destructors_for_temps.cpp:16:33:16:54 | Arg(this) | this:r16_5 |
| destructors_for_temps.cpp:16:33:16:54 | Arg(this) | this:r16_5 |
| destructors_for_temps.cpp:16:33:16:54 | CallTarget | func:r16_7 |
| destructors_for_temps.cpp:16:33:16:54 | ChiPartial | partial:m16_9 |
| destructors_for_temps.cpp:16:33:16:54 | ChiPartial | partial:m16_11 |
| destructors_for_temps.cpp:16:33:16:54 | ChiPartial | partial:m16_18 |
| destructors_for_temps.cpp:16:33:16:54 | ChiTotal | total:m15_13 |
| destructors_for_temps.cpp:16:33:16:54 | ChiTotal | total:m16_6 |
| destructors_for_temps.cpp:16:33:16:54 | ChiTotal | total:m16_12 |
| destructors_for_temps.cpp:16:33:16:54 | SideEffect | m16_12 |
| destructors_for_temps.cpp:16:33:16:54 | SideEffect | ~m15_13 |
| destructors_for_temps.cpp:16:56:16:60 | Arg(1) | 1:r16_14 |
| destructors_for_temps.cpp:16:56:16:60 | CallTarget | func:r16_13 |
| destructors_for_temps.cpp:16:56:16:60 | ChiPartial | partial:m16_15 |
| destructors_for_temps.cpp:16:56:16:60 | ChiTotal | total:m16_10 |
| destructors_for_temps.cpp:16:56:16:60 | SideEffect | ~m16_10 |
| destructors_for_temps.cpp:17:5:17:42 | Address | &:r17_1 |
| destructors_for_temps.cpp:17:12:17:33 | Address | &:r17_2 |
| destructors_for_temps.cpp:17:12:17:33 | Address | &:r17_2 |
| destructors_for_temps.cpp:17:12:17:33 | Address | &:r17_2 |
| destructors_for_temps.cpp:17:12:17:33 | Address | &:r17_2 |
| destructors_for_temps.cpp:17:12:17:33 | Arg(this) | this:r17_2 |
| destructors_for_temps.cpp:17:12:17:33 | Arg(this) | this:r17_2 |
| destructors_for_temps.cpp:17:12:17:33 | CallTarget | func:r17_4 |
| destructors_for_temps.cpp:17:12:17:33 | ChiPartial | partial:m17_6 |
| destructors_for_temps.cpp:17:12:17:33 | ChiPartial | partial:m17_8 |
| destructors_for_temps.cpp:17:12:17:33 | ChiPartial | partial:m17_15 |
| destructors_for_temps.cpp:17:12:17:33 | ChiTotal | total:m16_22 |
| destructors_for_temps.cpp:17:12:17:33 | ChiTotal | total:m17_3 |
| destructors_for_temps.cpp:17:12:17:33 | ChiTotal | total:m17_9 |
| destructors_for_temps.cpp:17:12:17:33 | SideEffect | m17_9 |
| destructors_for_temps.cpp:17:12:17:33 | SideEffect | ~m16_22 |
| destructors_for_temps.cpp:17:35:17:39 | CallTarget | func:r17_10 |
| destructors_for_temps.cpp:17:35:17:39 | ChiPartial | partial:m17_12 |
| destructors_for_temps.cpp:17:35:17:39 | ChiTotal | total:m17_7 |
| destructors_for_temps.cpp:17:35:17:39 | SideEffect | ~m17_7 |
| destructors_for_temps.cpp:17:35:17:39 | StoreValue | r17_11 |
| destructors_for_temps.cpp:21:6:21:15 | Address | &:r21_5 |
| destructors_for_temps.cpp:21:6:21:15 | ChiPartial | partial:m21_3 |
| destructors_for_temps.cpp:21:6:21:15 | ChiTotal | total:m21_2 |
| destructors_for_temps.cpp:21:6:21:15 | Load | m23_36 |
| destructors_for_temps.cpp:21:6:21:15 | SideEffect | ~m23_29 |
| destructors_for_temps.cpp:22:5:22:30 | Address | &:r22_3 |
| destructors_for_temps.cpp:22:5:22:30 | Address | &:r22_7 |
| destructors_for_temps.cpp:22:5:22:30 | Arg(0) | 0:r22_2 |
| destructors_for_temps.cpp:22:5:22:30 | Arg(this) | this:r22_7 |
| destructors_for_temps.cpp:22:5:22:30 | CallTarget | func:r22_1 |
| destructors_for_temps.cpp:22:5:22:30 | CallTarget | func:r22_8 |
| destructors_for_temps.cpp:22:5:22:30 | ChiPartial | partial:m22_4 |
| destructors_for_temps.cpp:22:5:22:30 | ChiPartial | partial:m22_10 |
| destructors_for_temps.cpp:22:5:22:30 | ChiPartial | partial:m22_12 |
| destructors_for_temps.cpp:22:5:22:30 | ChiTotal | total:m21_4 |
| destructors_for_temps.cpp:22:5:22:30 | ChiTotal | total:m22_5 |
| destructors_for_temps.cpp:22:5:22:30 | ChiTotal | total:m22_6 |
| destructors_for_temps.cpp:22:5:22:30 | SideEffect | ~m21_4 |
| destructors_for_temps.cpp:22:5:22:30 | SideEffect | ~m22_5 |
| destructors_for_temps.cpp:22:5:22:30 | Unary | r22_3 |
| destructors_for_temps.cpp:23:5:23:75 | Address | &:r23_1 |
| destructors_for_temps.cpp:23:12:23:33 | Address | &:r23_2 |
| destructors_for_temps.cpp:23:12:23:33 | Address | &:r23_2 |
| destructors_for_temps.cpp:23:12:23:33 | Address | &:r23_2 |
| destructors_for_temps.cpp:23:12:23:33 | Address | &:r23_2 |
| destructors_for_temps.cpp:23:12:23:33 | Arg(this) | this:r23_2 |
| destructors_for_temps.cpp:23:12:23:33 | Arg(this) | this:r23_2 |
| destructors_for_temps.cpp:23:12:23:33 | CallTarget | func:r23_4 |
| destructors_for_temps.cpp:23:12:23:33 | ChiPartial | partial:m23_6 |
| destructors_for_temps.cpp:23:12:23:33 | ChiPartial | partial:m23_8 |
| destructors_for_temps.cpp:23:12:23:33 | ChiPartial | partial:m23_15 |
| destructors_for_temps.cpp:23:12:23:33 | ChiTotal | total:m22_11 |
| destructors_for_temps.cpp:23:12:23:33 | ChiTotal | total:m23_3 |
| destructors_for_temps.cpp:23:12:23:33 | ChiTotal | total:m23_9 |
| destructors_for_temps.cpp:23:12:23:33 | SideEffect | m23_9 |
| destructors_for_temps.cpp:23:12:23:33 | SideEffect | ~m22_11 |
| destructors_for_temps.cpp:23:12:23:41 | Left | r23_17 |
| destructors_for_temps.cpp:23:12:23:74 | StoreValue | r23_35 |
| destructors_for_temps.cpp:23:12:23:74 | Unary | r23_34 |
| destructors_for_temps.cpp:23:35:23:39 | CallTarget | func:r23_10 |
| destructors_for_temps.cpp:23:35:23:39 | ChiPartial | partial:m23_12 |
| destructors_for_temps.cpp:23:35:23:39 | ChiTotal | total:m23_7 |
| destructors_for_temps.cpp:23:35:23:39 | SideEffect | ~m23_7 |
| destructors_for_temps.cpp:23:35:23:39 | Unary | r23_11 |
| destructors_for_temps.cpp:23:45:23:66 | Address | &:r23_18 |
| destructors_for_temps.cpp:23:45:23:66 | Address | &:r23_18 |
| destructors_for_temps.cpp:23:45:23:66 | Address | &:r23_18 |
| destructors_for_temps.cpp:23:45:23:66 | Address | &:r23_18 |
| destructors_for_temps.cpp:23:45:23:66 | Arg(this) | this:r23_18 |
| destructors_for_temps.cpp:23:45:23:66 | Arg(this) | this:r23_18 |
| destructors_for_temps.cpp:23:45:23:66 | CallTarget | func:r23_20 |
| destructors_for_temps.cpp:23:45:23:66 | ChiPartial | partial:m23_22 |
| destructors_for_temps.cpp:23:45:23:66 | ChiPartial | partial:m23_24 |
| destructors_for_temps.cpp:23:45:23:66 | ChiPartial | partial:m23_31 |
| destructors_for_temps.cpp:23:45:23:66 | ChiTotal | total:m23_13 |
| destructors_for_temps.cpp:23:45:23:66 | ChiTotal | total:m23_19 |
| destructors_for_temps.cpp:23:45:23:66 | ChiTotal | total:m23_25 |
| destructors_for_temps.cpp:23:45:23:66 | SideEffect | m23_25 |
| destructors_for_temps.cpp:23:45:23:66 | SideEffect | ~m23_13 |
| destructors_for_temps.cpp:23:45:23:74 | Right | r23_33 |
| destructors_for_temps.cpp:23:68:23:72 | CallTarget | func:r23_26 |
| destructors_for_temps.cpp:23:68:23:72 | ChiPartial | partial:m23_28 |
| destructors_for_temps.cpp:23:68:23:72 | ChiTotal | total:m23_23 |
| destructors_for_temps.cpp:23:68:23:72 | SideEffect | ~m23_23 |
| destructors_for_temps.cpp:23:68:23:72 | Unary | r23_27 |
| destructors_for_temps.cpp:29:6:29:15 | ChiPartial | partial:m29_3 |
| destructors_for_temps.cpp:29:6:29:15 | ChiTotal | total:m29_2 |
| destructors_for_temps.cpp:29:6:29:15 | SideEffect | ~m30_6 |
| destructors_for_temps.cpp:30:33:30:34 | Address | &:r30_1 |
| destructors_for_temps.cpp:30:38:30:70 | CallTarget | func:r30_3 |
| destructors_for_temps.cpp:30:38:30:70 | ChiPartial | partial:m30_5 |
| destructors_for_temps.cpp:30:38:30:70 | ChiTotal | total:m29_4 |
| destructors_for_temps.cpp:30:38:30:70 | SideEffect | ~m29_4 |
| destructors_for_temps.cpp:30:38:30:70 | StoreValue | r30_4 |
| destructors_for_temps.cpp:30:38:30:72 | Address | &:r30_2 |
| destructors_for_temps.cpp:30:38:30:72 | StoreValue | r30_9 |
| destructors_for_temps.cpp:30:38:30:72 | Unary | r30_2 |
| destructors_for_temps.cpp:30:38:30:72 | Unary | r30_8 |
| destructors_for_temps.cpp:33:6:33:15 | ChiPartial | partial:m33_3 |
| destructors_for_temps.cpp:33:6:33:15 | ChiTotal | total:m33_2 |
| destructors_for_temps.cpp:33:6:33:15 | SideEffect | ~m36_6 |
| destructors_for_temps.cpp:34:26:34:26 | Address | &:r34_1 |
| destructors_for_temps.cpp:34:26:34:26 | Address | &:r34_1 |
| destructors_for_temps.cpp:34:26:34:26 | Arg(this) | this:r34_1 |
| destructors_for_temps.cpp:34:26:34:26 | CallTarget | func:r34_3 |
| destructors_for_temps.cpp:34:26:34:26 | ChiPartial | partial:m34_5 |
| destructors_for_temps.cpp:34:26:34:26 | ChiPartial | partial:m34_7 |
| destructors_for_temps.cpp:34:26:34:26 | ChiTotal | total:m33_4 |
| destructors_for_temps.cpp:34:26:34:26 | ChiTotal | total:m34_2 |
| destructors_for_temps.cpp:34:26:34:26 | SideEffect | ~m33_4 |
| destructors_for_temps.cpp:35:33:35:35 | Address | &:r35_1 |
| destructors_for_temps.cpp:35:39:35:71 | CallTarget | func:r35_3 |
| destructors_for_temps.cpp:35:39:35:71 | ChiPartial | partial:m35_5 |
| destructors_for_temps.cpp:35:39:35:71 | ChiTotal | total:m34_6 |
| destructors_for_temps.cpp:35:39:35:71 | SideEffect | ~m34_6 |
| destructors_for_temps.cpp:35:39:35:71 | StoreValue | r35_4 |
| destructors_for_temps.cpp:35:39:35:73 | Address | &:r35_2 |
| destructors_for_temps.cpp:35:39:35:73 | StoreValue | r35_9 |
| destructors_for_temps.cpp:35:39:35:73 | Unary | r35_2 |
| destructors_for_temps.cpp:35:39:35:73 | Unary | r35_8 |
| destructors_for_temps.cpp:36:1:36:1 | Address | &:r36_2 |
| destructors_for_temps.cpp:36:1:36:1 | Address | &:r36_2 |
| destructors_for_temps.cpp:36:1:36:1 | Arg(this) | this:r36_2 |
| destructors_for_temps.cpp:36:1:36:1 | CallTarget | func:r36_3 |
| destructors_for_temps.cpp:36:1:36:1 | ChiPartial | partial:m36_5 |
| destructors_for_temps.cpp:36:1:36:1 | ChiPartial | partial:m36_8 |
| destructors_for_temps.cpp:36:1:36:1 | ChiTotal | total:m34_8 |
| destructors_for_temps.cpp:36:1:36:1 | ChiTotal | total:m35_6 |
| destructors_for_temps.cpp:36:1:36:1 | SideEffect | m34_8 |
| destructors_for_temps.cpp:36:1:36:1 | SideEffect | ~m35_6 |
| destructors_for_temps.cpp:38:6:38:15 | ChiPartial | partial:m38_3 |
| destructors_for_temps.cpp:38:6:38:15 | ChiTotal | total:m38_2 |
| destructors_for_temps.cpp:38:6:38:15 | SideEffect | ~m39_5 |
| destructors_for_temps.cpp:38:22:38:22 | Address | &:r38_5 |
| destructors_for_temps.cpp:39:3:39:3 | Address | &:r39_2 |
| destructors_for_temps.cpp:39:3:39:3 | Address | &:r39_7 |
| destructors_for_temps.cpp:39:3:39:3 | Address | &:r39_19 |
| destructors_for_temps.cpp:39:3:39:3 | Address | &:r39_30 |
| destructors_for_temps.cpp:39:3:39:3 | Condition | r39_3 |
| destructors_for_temps.cpp:39:3:39:3 | Load | m38_6 |
| destructors_for_temps.cpp:39:3:39:3 | Load | m39_6 |
| destructors_for_temps.cpp:39:3:39:3 | Phi | from 2:m39_20 |
| destructors_for_temps.cpp:39:3:39:3 | Phi | from 2:~m39_15 |
| destructors_for_temps.cpp:39:3:39:3 | Phi | from 3:m39_31 |
| destructors_for_temps.cpp:39:3:39:3 | Phi | from 3:~m39_26 |
| destructors_for_temps.cpp:39:3:39:3 | StoreValue | r39_8 |
| destructors_for_temps.cpp:39:3:39:53 | Address | &:r39_1 |
| destructors_for_temps.cpp:39:7:39:28 | Address | &:r39_10 |
| destructors_for_temps.cpp:39:7:39:28 | Address | &:r39_10 |
| destructors_for_temps.cpp:39:7:39:28 | Address | &:r39_10 |
| destructors_for_temps.cpp:39:7:39:28 | Arg(this) | this:r39_10 |
| destructors_for_temps.cpp:39:7:39:28 | CallTarget | func:r39_12 |
| destructors_for_temps.cpp:39:7:39:28 | ChiPartial | partial:m39_14 |
| destructors_for_temps.cpp:39:7:39:28 | ChiPartial | partial:m39_16 |
| destructors_for_temps.cpp:39:7:39:28 | ChiTotal | total:m38_4 |
| destructors_for_temps.cpp:39:7:39:28 | ChiTotal | total:m39_11 |
| destructors_for_temps.cpp:39:7:39:28 | Load | m39_17 |
| destructors_for_temps.cpp:39:7:39:28 | SideEffect | ~m38_4 |
| destructors_for_temps.cpp:39:7:39:28 | StoreValue | r39_18 |
| destructors_for_temps.cpp:39:32:39:53 | Address | &:r39_21 |
| destructors_for_temps.cpp:39:32:39:53 | Address | &:r39_21 |
| destructors_for_temps.cpp:39:32:39:53 | Address | &:r39_21 |
| destructors_for_temps.cpp:39:32:39:53 | Arg(this) | this:r39_21 |
| destructors_for_temps.cpp:39:32:39:53 | CallTarget | func:r39_23 |
| destructors_for_temps.cpp:39:32:39:53 | ChiPartial | partial:m39_25 |
| destructors_for_temps.cpp:39:32:39:53 | ChiPartial | partial:m39_27 |
| destructors_for_temps.cpp:39:32:39:53 | ChiTotal | total:m38_4 |
| destructors_for_temps.cpp:39:32:39:53 | ChiTotal | total:m39_22 |
| destructors_for_temps.cpp:39:32:39:53 | Load | m39_28 |
| destructors_for_temps.cpp:39:32:39:53 | SideEffect | ~m38_4 |
| destructors_for_temps.cpp:39:32:39:53 | StoreValue | r39_29 |
| destructors_for_temps.cpp:42:6:42:15 | ChiPartial | partial:m42_3 |
| destructors_for_temps.cpp:42:6:42:15 | ChiTotal | total:m42_2 |
| destructors_for_temps.cpp:42:6:42:15 | Phi | from 2:~m45_22 |
| destructors_for_temps.cpp:42:6:42:15 | Phi | from 4:~m47_6 |
| destructors_for_temps.cpp:42:6:42:15 | SideEffect | ~m42_7 |
| destructors_for_temps.cpp:42:22:42:22 | Address | &:r42_5 |
| destructors_for_temps.cpp:43:26:43:26 | Address | &:r43_1 |
| destructors_for_temps.cpp:43:26:43:26 | Address | &:r43_1 |
| destructors_for_temps.cpp:43:26:43:26 | Arg(this) | this:r43_1 |
| destructors_for_temps.cpp:43:26:43:26 | CallTarget | func:r43_3 |
| destructors_for_temps.cpp:43:26:43:26 | ChiPartial | partial:m43_5 |
| destructors_for_temps.cpp:43:26:43:26 | ChiPartial | partial:m43_7 |
| destructors_for_temps.cpp:43:26:43:26 | ChiTotal | total:m42_4 |
| destructors_for_temps.cpp:43:26:43:26 | ChiTotal | total:m43_2 |
| destructors_for_temps.cpp:43:26:43:26 | SideEffect | ~m42_4 |
| destructors_for_temps.cpp:44:9:44:9 | Address | &:r44_1 |
| destructors_for_temps.cpp:44:9:44:9 | Condition | r44_2 |
| destructors_for_temps.cpp:44:9:44:9 | Load | m42_6 |
| destructors_for_temps.cpp:45:7:45:69 | Address | &:r45_1 |
| destructors_for_temps.cpp:45:7:45:69 | Address | &:r45_1 |
| destructors_for_temps.cpp:45:7:45:69 | Address | &:r45_1 |
| destructors_for_temps.cpp:45:7:45:69 | Arg(this) | this:r45_1 |
| destructors_for_temps.cpp:45:7:45:69 | CallTarget | func:r45_3 |
| destructors_for_temps.cpp:45:7:45:69 | ChiPartial | partial:m45_21 |
| destructors_for_temps.cpp:45:7:45:69 | ChiPartial | partial:m45_23 |
| destructors_for_temps.cpp:45:7:45:69 | ChiTotal | total:m45_2 |
| destructors_for_temps.cpp:45:7:45:69 | ChiTotal | total:m45_16 |
| destructors_for_temps.cpp:45:7:45:69 | Load | m45_24 |
| destructors_for_temps.cpp:45:7:45:69 | SideEffect | ~m45_16 |
| destructors_for_temps.cpp:45:34:45:36 | Arg(0) | 0:r45_4 |
| destructors_for_temps.cpp:45:39:45:60 | Address | &:r45_5 |
| destructors_for_temps.cpp:45:39:45:60 | Address | &:r45_5 |
| destructors_for_temps.cpp:45:39:45:60 | Address | &:r45_5 |
| destructors_for_temps.cpp:45:39:45:60 | Address | &:r45_5 |
| destructors_for_temps.cpp:45:39:45:60 | Arg(this) | this:r45_5 |
| destructors_for_temps.cpp:45:39:45:60 | Arg(this) | this:r45_5 |
| destructors_for_temps.cpp:45:39:45:60 | CallTarget | func:r45_7 |
| destructors_for_temps.cpp:45:39:45:60 | ChiPartial | partial:m45_9 |
| destructors_for_temps.cpp:45:39:45:60 | ChiPartial | partial:m45_11 |
| destructors_for_temps.cpp:45:39:45:60 | ChiPartial | partial:m45_18 |
| destructors_for_temps.cpp:45:39:45:60 | ChiTotal | total:m43_6 |
| destructors_for_temps.cpp:45:39:45:60 | ChiTotal | total:m45_6 |
| destructors_for_temps.cpp:45:39:45:60 | ChiTotal | total:m45_12 |
| destructors_for_temps.cpp:45:39:45:60 | SideEffect | m45_12 |
| destructors_for_temps.cpp:45:39:45:60 | SideEffect | ~m43_6 |
| destructors_for_temps.cpp:45:62:45:66 | Arg(1) | 1:r45_14 |
| destructors_for_temps.cpp:45:62:45:66 | CallTarget | func:r45_13 |
| destructors_for_temps.cpp:45:62:45:66 | ChiPartial | partial:m45_15 |
| destructors_for_temps.cpp:45:62:45:66 | ChiTotal | total:m45_10 |
| destructors_for_temps.cpp:45:62:45:66 | SideEffect | ~m45_10 |
| destructors_for_temps.cpp:47:1:47:1 | Address | &:r47_2 |
| destructors_for_temps.cpp:47:1:47:1 | Address | &:r47_2 |
| destructors_for_temps.cpp:47:1:47:1 | Arg(this) | this:r47_2 |
| destructors_for_temps.cpp:47:1:47:1 | CallTarget | func:r47_3 |
| destructors_for_temps.cpp:47:1:47:1 | ChiPartial | partial:m47_5 |
| destructors_for_temps.cpp:47:1:47:1 | ChiPartial | partial:m47_8 |
| destructors_for_temps.cpp:47:1:47:1 | ChiTotal | total:m43_6 |
| destructors_for_temps.cpp:47:1:47:1 | ChiTotal | total:m43_8 |
| destructors_for_temps.cpp:47:1:47:1 | SideEffect | m43_8 |
| destructors_for_temps.cpp:47:1:47:1 | SideEffect | ~m43_6 |
| destructors_for_temps.cpp:49:6:49:15 | ChiPartial | partial:m49_3 |
| destructors_for_temps.cpp:49:6:49:15 | ChiTotal | total:m49_2 |
| destructors_for_temps.cpp:49:6:49:15 | Phi | from 2:~m51_26 |
| destructors_for_temps.cpp:49:6:49:15 | Phi | from 4:~m52_6 |
| destructors_for_temps.cpp:49:6:49:15 | SideEffect | ~m49_7 |
| destructors_for_temps.cpp:49:22:49:22 | Address | &:r49_5 |
| destructors_for_temps.cpp:50:26:50:26 | Address | &:r50_1 |
| destructors_for_temps.cpp:50:26:50:26 | Address | &:r50_1 |
| destructors_for_temps.cpp:50:26:50:26 | Arg(this) | this:r50_1 |
| destructors_for_temps.cpp:50:26:50:26 | CallTarget | func:r50_3 |
| destructors_for_temps.cpp:50:26:50:26 | ChiPartial | partial:m50_5 |
| destructors_for_temps.cpp:50:26:50:26 | ChiPartial | partial:m50_7 |
| destructors_for_temps.cpp:50:26:50:26 | ChiTotal | total:m49_4 |
| destructors_for_temps.cpp:50:26:50:26 | ChiTotal | total:m50_2 |
| destructors_for_temps.cpp:50:26:50:26 | SideEffect | ~m49_4 |
| destructors_for_temps.cpp:51:5:51:5 | Address | &:r51_2 |
| destructors_for_temps.cpp:51:5:51:5 | Address | &:r51_39 |
| destructors_for_temps.cpp:51:5:51:5 | Address | &:r51_41 |
| destructors_for_temps.cpp:51:5:51:5 | Condition | r51_3 |
| destructors_for_temps.cpp:51:5:51:5 | Load | m49_6 |
| destructors_for_temps.cpp:51:5:51:5 | Load | m51_40 |
| destructors_for_temps.cpp:51:5:51:5 | StoreValue | r51_42 |
| destructors_for_temps.cpp:51:5:51:96 | Address | &:r51_1 |
| destructors_for_temps.cpp:51:9:51:71 | Address | &:r51_5 |
| destructors_for_temps.cpp:51:9:51:71 | Address | &:r51_5 |
| destructors_for_temps.cpp:51:9:51:71 | Address | &:r51_5 |
| destructors_for_temps.cpp:51:9:51:71 | Arg(this) | this:r51_5 |
| destructors_for_temps.cpp:51:9:51:71 | CallTarget | func:r51_7 |
| destructors_for_temps.cpp:51:9:51:71 | ChiPartial | partial:m51_25 |
| destructors_for_temps.cpp:51:9:51:71 | ChiPartial | partial:m51_27 |
| destructors_for_temps.cpp:51:9:51:71 | ChiTotal | total:m51_6 |
| destructors_for_temps.cpp:51:9:51:71 | ChiTotal | total:m51_20 |
| destructors_for_temps.cpp:51:9:51:71 | Load | m51_28 |
| destructors_for_temps.cpp:51:9:51:71 | SideEffect | ~m51_20 |
| destructors_for_temps.cpp:51:36:51:38 | Arg(0) | 0:r51_8 |
| destructors_for_temps.cpp:51:41:51:62 | Address | &:r51_9 |
| destructors_for_temps.cpp:51:41:51:62 | Address | &:r51_9 |
| destructors_for_temps.cpp:51:41:51:62 | Address | &:r51_9 |
| destructors_for_temps.cpp:51:41:51:62 | Address | &:r51_9 |
| destructors_for_temps.cpp:51:41:51:62 | Arg(this) | this:r51_9 |
| destructors_for_temps.cpp:51:41:51:62 | Arg(this) | this:r51_9 |
| destructors_for_temps.cpp:51:41:51:62 | CallTarget | func:r51_11 |
| destructors_for_temps.cpp:51:41:51:62 | ChiPartial | partial:m51_13 |
| destructors_for_temps.cpp:51:41:51:62 | ChiPartial | partial:m51_15 |
| destructors_for_temps.cpp:51:41:51:62 | ChiPartial | partial:m51_22 |
| destructors_for_temps.cpp:51:41:51:62 | ChiTotal | total:m50_6 |
| destructors_for_temps.cpp:51:41:51:62 | ChiTotal | total:m51_10 |
| destructors_for_temps.cpp:51:41:51:62 | ChiTotal | total:m51_16 |
| destructors_for_temps.cpp:51:41:51:62 | SideEffect | m51_16 |
| destructors_for_temps.cpp:51:41:51:62 | SideEffect | ~m50_6 |
| destructors_for_temps.cpp:51:64:51:68 | Arg(1) | 1:r51_18 |
| destructors_for_temps.cpp:51:64:51:68 | CallTarget | func:r51_17 |
| destructors_for_temps.cpp:51:64:51:68 | ChiPartial | partial:m51_19 |
| destructors_for_temps.cpp:51:64:51:68 | ChiTotal | total:m51_14 |
| destructors_for_temps.cpp:51:64:51:68 | SideEffect | ~m51_14 |
| destructors_for_temps.cpp:51:75:51:96 | Address | &:r51_30 |
| destructors_for_temps.cpp:51:75:51:96 | Address | &:r51_30 |
| destructors_for_temps.cpp:51:75:51:96 | Address | &:r51_30 |
| destructors_for_temps.cpp:51:75:51:96 | Arg(this) | this:r51_30 |
| destructors_for_temps.cpp:51:75:51:96 | CallTarget | func:r51_32 |
| destructors_for_temps.cpp:51:75:51:96 | ChiPartial | partial:m51_34 |
| destructors_for_temps.cpp:51:75:51:96 | ChiPartial | partial:m51_36 |
| destructors_for_temps.cpp:51:75:51:96 | ChiTotal | total:m50_6 |
| destructors_for_temps.cpp:51:75:51:96 | ChiTotal | total:m51_31 |
| destructors_for_temps.cpp:51:75:51:96 | Load | m51_37 |
| destructors_for_temps.cpp:51:75:51:96 | SideEffect | ~m50_6 |
| destructors_for_temps.cpp:51:75:51:96 | StoreValue | r51_38 |
| destructors_for_temps.cpp:52:1:52:1 | Address | &:r52_2 |
| destructors_for_temps.cpp:52:1:52:1 | Address | &:r52_2 |
| destructors_for_temps.cpp:52:1:52:1 | Arg(this) | this:r52_2 |
| destructors_for_temps.cpp:52:1:52:1 | CallTarget | func:r52_3 |
| destructors_for_temps.cpp:52:1:52:1 | ChiPartial | partial:m52_5 |
| destructors_for_temps.cpp:52:1:52:1 | ChiPartial | partial:m52_8 |
| destructors_for_temps.cpp:52:1:52:1 | ChiTotal | total:m50_8 |
| destructors_for_temps.cpp:52:1:52:1 | ChiTotal | total:m51_35 |
| destructors_for_temps.cpp:52:1:52:1 | SideEffect | m50_8 |
| destructors_for_temps.cpp:52:1:52:1 | SideEffect | ~m51_35 |
| destructors_for_temps.cpp:54:6:54:15 | ChiPartial | partial:m54_3 |
| destructors_for_temps.cpp:54:6:54:15 | ChiTotal | total:m54_2 |
| destructors_for_temps.cpp:54:6:54:15 | Phi | from 2:~m55_26 |
| destructors_for_temps.cpp:54:6:54:15 | Phi | from 4:~m55_35 |
| destructors_for_temps.cpp:54:6:54:15 | SideEffect | ~m54_7 |
| destructors_for_temps.cpp:54:22:54:22 | Address | &:r54_5 |
| destructors_for_temps.cpp:55:5:55:5 | Address | &:r55_2 |
| destructors_for_temps.cpp:55:5:55:5 | Address | &:r55_39 |
| destructors_for_temps.cpp:55:5:55:5 | Address | &:r55_41 |
| destructors_for_temps.cpp:55:5:55:5 | Condition | r55_3 |
| destructors_for_temps.cpp:55:5:55:5 | Load | m54_6 |
| destructors_for_temps.cpp:55:5:55:5 | Load | m55_40 |
| destructors_for_temps.cpp:55:5:55:5 | StoreValue | r55_42 |
| destructors_for_temps.cpp:55:5:55:96 | Address | &:r55_1 |
| destructors_for_temps.cpp:55:9:55:71 | Address | &:r55_5 |
| destructors_for_temps.cpp:55:9:55:71 | Address | &:r55_5 |
| destructors_for_temps.cpp:55:9:55:71 | Address | &:r55_5 |
| destructors_for_temps.cpp:55:9:55:71 | Arg(this) | this:r55_5 |
| destructors_for_temps.cpp:55:9:55:71 | CallTarget | func:r55_7 |
| destructors_for_temps.cpp:55:9:55:71 | ChiPartial | partial:m55_25 |
| destructors_for_temps.cpp:55:9:55:71 | ChiPartial | partial:m55_27 |
| destructors_for_temps.cpp:55:9:55:71 | ChiTotal | total:m55_6 |
| destructors_for_temps.cpp:55:9:55:71 | ChiTotal | total:m55_20 |
| destructors_for_temps.cpp:55:9:55:71 | Load | m55_28 |
| destructors_for_temps.cpp:55:9:55:71 | SideEffect | ~m55_20 |
| destructors_for_temps.cpp:55:36:55:38 | Arg(0) | 0:r55_8 |
| destructors_for_temps.cpp:55:41:55:62 | Address | &:r55_9 |
| destructors_for_temps.cpp:55:41:55:62 | Address | &:r55_9 |
| destructors_for_temps.cpp:55:41:55:62 | Address | &:r55_9 |
| destructors_for_temps.cpp:55:41:55:62 | Address | &:r55_9 |
| destructors_for_temps.cpp:55:41:55:62 | Arg(this) | this:r55_9 |
| destructors_for_temps.cpp:55:41:55:62 | Arg(this) | this:r55_9 |
| destructors_for_temps.cpp:55:41:55:62 | CallTarget | func:r55_11 |
| destructors_for_temps.cpp:55:41:55:62 | ChiPartial | partial:m55_13 |
| destructors_for_temps.cpp:55:41:55:62 | ChiPartial | partial:m55_15 |
| destructors_for_temps.cpp:55:41:55:62 | ChiPartial | partial:m55_22 |
| destructors_for_temps.cpp:55:41:55:62 | ChiTotal | total:m54_4 |
| destructors_for_temps.cpp:55:41:55:62 | ChiTotal | total:m55_10 |
| destructors_for_temps.cpp:55:41:55:62 | ChiTotal | total:m55_16 |
| destructors_for_temps.cpp:55:41:55:62 | SideEffect | m55_16 |
| destructors_for_temps.cpp:55:41:55:62 | SideEffect | ~m54_4 |
| destructors_for_temps.cpp:55:64:55:68 | Arg(1) | 1:r55_18 |
| destructors_for_temps.cpp:55:64:55:68 | CallTarget | func:r55_17 |
| destructors_for_temps.cpp:55:64:55:68 | ChiPartial | partial:m55_19 |
| destructors_for_temps.cpp:55:64:55:68 | ChiTotal | total:m55_14 |
| destructors_for_temps.cpp:55:64:55:68 | SideEffect | ~m55_14 |
| destructors_for_temps.cpp:55:75:55:96 | Address | &:r55_30 |
| destructors_for_temps.cpp:55:75:55:96 | Address | &:r55_30 |
| destructors_for_temps.cpp:55:75:55:96 | Address | &:r55_30 |
| destructors_for_temps.cpp:55:75:55:96 | Arg(this) | this:r55_30 |
| destructors_for_temps.cpp:55:75:55:96 | CallTarget | func:r55_32 |
| destructors_for_temps.cpp:55:75:55:96 | ChiPartial | partial:m55_34 |
| destructors_for_temps.cpp:55:75:55:96 | ChiPartial | partial:m55_36 |
| destructors_for_temps.cpp:55:75:55:96 | ChiTotal | total:m54_4 |
| destructors_for_temps.cpp:55:75:55:96 | ChiTotal | total:m55_31 |
| destructors_for_temps.cpp:55:75:55:96 | Load | m55_37 |
| destructors_for_temps.cpp:55:75:55:96 | SideEffect | ~m54_4 |
| destructors_for_temps.cpp:55:75:55:96 | StoreValue | r55_38 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
@@ -726,6 +1160,8 @@
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_4 |
| file://:0:0:0:0 | Address | &:r0_4 |
| file://:0:0:0:0 | Address | &:r0_5 |
@@ -861,6 +1297,7 @@
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_5 |
| file://:0:0:0:0 | Load | m0_8 |
| file://:0:0:0:0 | Load | m0_11 |
@@ -900,6 +1337,7 @@
| file://:0:0:0:0 | SideEffect | m0_4 |
| file://:0:0:0:0 | SideEffect | m0_4 |
| file://:0:0:0:0 | SideEffect | m0_4 |
| file://:0:0:0:0 | SideEffect | m0_4 |
| file://:0:0:0:0 | SideEffect | m0_14 |
| file://:0:0:0:0 | SideEffect | m1080_23 |
| file://:0:0:0:0 | SideEffect | m1080_23 |

View File

@@ -724,6 +724,420 @@ complex.c:
# 58| v58_5(void) = AliasedUse : ~m?
# 58| v58_6(void) = ExitFunction :
destructors_for_temps.cpp:
# 9| void ClassWithConstructor::ClassWithConstructor(ClassWithConstructor&&)
# 9| Block 0
# 9| v9_1(void) = EnterFunction :
# 9| mu9_2(unknown) = AliasedDefinition :
# 9| mu9_3(unknown) = InitializeNonLocal :
# 9| r9_4(glval<unknown>) = VariableAddress[#this] :
# 9| mu9_5(glval<ClassWithConstructor>) = InitializeParameter[#this] : &:r9_4
# 9| r9_6(glval<ClassWithConstructor>) = Load[#this] : &:r9_4, ~m?
# 9| mu9_7(ClassWithConstructor) = InitializeIndirection[#this] : &:r9_6
#-----| r0_1(glval<ClassWithConstructor &&>) = VariableAddress[(unnamed parameter 0)] :
#-----| mu0_2(ClassWithConstructor &&) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
#-----| r0_3(ClassWithConstructor &&) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
# 9| v9_8(void) = NoOp :
# 9| v9_9(void) = ReturnIndirection[#this] : &:r9_6, ~m?
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
# 9| v9_10(void) = ReturnVoid :
# 9| v9_11(void) = AliasedUse : ~m?
# 9| v9_12(void) = ExitFunction :
# 14| char temp_test()
# 14| Block 0
# 14| v14_1(void) = EnterFunction :
# 14| mu14_2(unknown) = AliasedDefinition :
# 14| mu14_3(unknown) = InitializeNonLocal :
# 15| r15_1(glval<char>) = VariableAddress[x] :
# 15| r15_2(glval<ClassWithDestructor2>) = VariableAddress[#temp15:14] :
# 15| mu15_3(ClassWithDestructor2) = Uninitialized[#temp15:14] : &:r15_2
# 15| r15_4(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 15| v15_5(void) = Call[ClassWithDestructor2] : func:r15_4, this:r15_2
# 15| mu15_6(unknown) = ^CallSideEffect : ~m?
# 15| mu15_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r15_2
# 15| r15_8(glval<unknown>) = FunctionAddress[get_x] :
# 15| r15_9(char) = Call[get_x] : func:r15_8, this:r15_2
# 15| mu15_10(unknown) = ^CallSideEffect : ~m?
# 15| v15_11(void) = ^IndirectReadSideEffect[-1] : &:r15_2, ~m?
# 15| mu15_12(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r15_2
# 15| mu15_13(char) = Store[x] : &:r15_1, r15_9
# 16| r16_1(glval<ClassWithConstructor>) = VariableAddress[y] :
# 16| mu16_2(ClassWithConstructor) = Uninitialized[y] : &:r16_1
# 16| r16_3(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 16| r16_4(char) = Constant[97] :
# 16| r16_5(glval<ClassWithDestructor2>) = VariableAddress[#temp16:33] :
# 16| mu16_6(ClassWithDestructor2) = Uninitialized[#temp16:33] : &:r16_5
# 16| r16_7(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 16| v16_8(void) = Call[ClassWithDestructor2] : func:r16_7, this:r16_5
# 16| mu16_9(unknown) = ^CallSideEffect : ~m?
# 16| mu16_10(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r16_5
# 16| r16_11(glval<unknown>) = FunctionAddress[get_x] :
# 16| r16_12(char) = Call[get_x] : func:r16_11, this:r16_5
# 16| mu16_13(unknown) = ^CallSideEffect : ~m?
# 16| v16_14(void) = ^IndirectReadSideEffect[-1] : &:r16_5, ~m?
# 16| mu16_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r16_5
# 16| v16_16(void) = Call[ClassWithConstructor] : func:r16_3, this:r16_1, 0:r16_4, 1:r16_12
# 16| mu16_17(unknown) = ^CallSideEffect : ~m?
# 16| mu16_18(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r16_1
# 17| r17_1(glval<char>) = VariableAddress[#return] :
# 17| r17_2(glval<ClassWithDestructor2>) = VariableAddress[#temp17:12] :
# 17| mu17_3(ClassWithDestructor2) = Uninitialized[#temp17:12] : &:r17_2
# 17| r17_4(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 17| v17_5(void) = Call[ClassWithDestructor2] : func:r17_4, this:r17_2
# 17| mu17_6(unknown) = ^CallSideEffect : ~m?
# 17| mu17_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r17_2
# 17| r17_8(glval<unknown>) = FunctionAddress[get_x] :
# 17| r17_9(char) = Call[get_x] : func:r17_8, this:r17_2
# 17| mu17_10(unknown) = ^CallSideEffect : ~m?
# 17| v17_11(void) = ^IndirectReadSideEffect[-1] : &:r17_2, ~m?
# 17| mu17_12(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r17_2
# 17| mu17_13(char) = Store[#return] : &:r17_1, r17_9
# 14| r14_4(glval<char>) = VariableAddress[#return] :
# 14| v14_5(void) = ReturnValue : &:r14_4, ~m?
# 14| v14_6(void) = AliasedUse : ~m?
# 14| v14_7(void) = ExitFunction :
# 21| char temp_test2()
# 21| Block 0
# 21| v21_1(void) = EnterFunction :
# 21| mu21_2(unknown) = AliasedDefinition :
# 21| mu21_3(unknown) = InitializeNonLocal :
# 22| r22_1(glval<unknown>) = FunctionAddress[operator new] :
# 22| r22_2(unsigned long) = Constant[1] :
# 22| r22_3(void *) = Call[operator new] : func:r22_1, 0:r22_2
# 22| mu22_4(unknown) = ^CallSideEffect : ~m?
# 22| mu22_5(unknown) = ^InitializeDynamicAllocation : &:r22_3
# 22| r22_6(ClassWithDestructor2 *) = Convert : r22_3
# 22| r22_7(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 22| v22_8(void) = Call[ClassWithDestructor2] : func:r22_7, this:r22_6
# 22| mu22_9(unknown) = ^CallSideEffect : ~m?
# 22| mu22_10(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r22_6
# 23| r23_1(glval<char>) = VariableAddress[#return] :
# 23| r23_2(glval<ClassWithDestructor2>) = VariableAddress[#temp23:12] :
# 23| mu23_3(ClassWithDestructor2) = Uninitialized[#temp23:12] : &:r23_2
# 23| r23_4(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 23| v23_5(void) = Call[ClassWithDestructor2] : func:r23_4, this:r23_2
# 23| mu23_6(unknown) = ^CallSideEffect : ~m?
# 23| mu23_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_2
# 23| r23_8(glval<unknown>) = FunctionAddress[get_x] :
# 23| r23_9(char) = Call[get_x] : func:r23_8, this:r23_2
# 23| mu23_10(unknown) = ^CallSideEffect : ~m?
# 23| v23_11(void) = ^IndirectReadSideEffect[-1] : &:r23_2, ~m?
# 23| mu23_12(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_2
# 23| r23_13(int) = Convert : r23_9
# 23| r23_14(glval<ClassWithDestructor2>) = VariableAddress[#temp23:45] :
# 23| mu23_15(ClassWithDestructor2) = Uninitialized[#temp23:45] : &:r23_14
# 23| r23_16(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 23| v23_17(void) = Call[ClassWithDestructor2] : func:r23_16, this:r23_14
# 23| mu23_18(unknown) = ^CallSideEffect : ~m?
# 23| mu23_19(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_14
# 23| r23_20(glval<unknown>) = FunctionAddress[get_x] :
# 23| r23_21(char) = Call[get_x] : func:r23_20, this:r23_14
# 23| mu23_22(unknown) = ^CallSideEffect : ~m?
# 23| v23_23(void) = ^IndirectReadSideEffect[-1] : &:r23_14, ~m?
# 23| mu23_24(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r23_14
# 23| r23_25(int) = Convert : r23_21
# 23| r23_26(int) = Add : r23_13, r23_25
# 23| r23_27(char) = Convert : r23_26
# 23| mu23_28(char) = Store[#return] : &:r23_1, r23_27
# 21| r21_4(glval<char>) = VariableAddress[#return] :
# 21| v21_5(void) = ReturnValue : &:r21_4, ~m?
# 21| v21_6(void) = AliasedUse : ~m?
# 21| v21_7(void) = ExitFunction :
# 29| void temp_test3()
# 29| Block 0
# 29| v29_1(void) = EnterFunction :
# 29| mu29_2(unknown) = AliasedDefinition :
# 29| mu29_3(unknown) = InitializeNonLocal :
# 30| r30_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs] :
# 30| r30_2(glval<ClassWithDestructor2>) = VariableAddress[#temp30:38] :
# 30| r30_3(glval<unknown>) = FunctionAddress[returnValue] :
# 30| r30_4(ClassWithDestructor2) = Call[returnValue] : func:r30_3
# 30| mu30_5(unknown) = ^CallSideEffect : ~m?
# 30| mu30_6(ClassWithDestructor2) = Store[#temp30:38] : &:r30_2, r30_4
# 30| r30_7(glval<ClassWithDestructor2>) = Convert : r30_2
# 30| r30_8(ClassWithDestructor2 &) = CopyValue : r30_7
# 30| mu30_9(ClassWithDestructor2 &) = Store[rs] : &:r30_1, r30_8
# 31| v31_1(void) = NoOp :
# 29| v29_4(void) = ReturnVoid :
# 29| v29_5(void) = AliasedUse : ~m?
# 29| v29_6(void) = ExitFunction :
# 33| void temp_test4()
# 33| Block 0
# 33| v33_1(void) = EnterFunction :
# 33| mu33_2(unknown) = AliasedDefinition :
# 33| mu33_3(unknown) = InitializeNonLocal :
# 34| r34_1(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 34| mu34_2(ClassWithDestructor2) = Uninitialized[c] : &:r34_1
# 34| r34_3(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 34| v34_4(void) = Call[ClassWithDestructor2] : func:r34_3, this:r34_1
# 34| mu34_5(unknown) = ^CallSideEffect : ~m?
# 34| mu34_6(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r34_1
# 35| r35_1(glval<ClassWithDestructor2 &>) = VariableAddress[rs2] :
# 35| r35_2(glval<ClassWithDestructor2>) = VariableAddress[#temp35:39] :
# 35| r35_3(glval<unknown>) = FunctionAddress[returnValue] :
# 35| r35_4(ClassWithDestructor2) = Call[returnValue] : func:r35_3
# 35| mu35_5(unknown) = ^CallSideEffect : ~m?
# 35| mu35_6(ClassWithDestructor2) = Store[#temp35:39] : &:r35_2, r35_4
# 35| r35_7(glval<ClassWithDestructor2>) = Convert : r35_2
# 35| r35_8(ClassWithDestructor2 &) = CopyValue : r35_7
# 35| mu35_9(ClassWithDestructor2 &) = Store[rs2] : &:r35_1, r35_8
# 36| v36_1(void) = NoOp :
# 36| r36_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 36| r36_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
# 36| v36_4(void) = Call[~ClassWithDestructor2] : func:r36_3, this:r36_2
# 36| mu36_5(unknown) = ^CallSideEffect : ~m?
# 36| v36_6(void) = ^IndirectReadSideEffect[-1] : &:r36_2, ~m?
# 36| mu36_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r36_2
# 33| v33_4(void) = ReturnVoid :
# 33| v33_5(void) = AliasedUse : ~m?
# 33| v33_6(void) = ExitFunction :
# 38| void temp_test5(bool)
# 38| Block 0
# 38| v38_1(void) = EnterFunction :
# 38| mu38_2(unknown) = AliasedDefinition :
# 38| mu38_3(unknown) = InitializeNonLocal :
# 38| r38_4(glval<bool>) = VariableAddress[b] :
# 38| mu38_5(bool) = InitializeParameter[b] : &:r38_4
# 39| r39_1(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| r39_2(glval<bool>) = VariableAddress[b] :
# 39| r39_3(bool) = Load[b] : &:r39_2, ~m?
# 39| v39_4(void) = ConditionalBranch : r39_3
#-----| False -> Block 3
#-----| True -> Block 2
# 39| Block 1
# 39| r39_5(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| r39_6(ClassWithDestructor2) = Load[#temp39:3] : &:r39_5, ~m?
# 39| mu39_7(ClassWithDestructor2) = Store[#temp39:3] : &:r39_1, r39_6
# 40| v40_1(void) = NoOp :
# 38| v38_6(void) = ReturnVoid :
# 38| v38_7(void) = AliasedUse : ~m?
# 38| v38_8(void) = ExitFunction :
# 39| Block 2
# 39| r39_8(glval<ClassWithDestructor2>) = VariableAddress[#temp39:7] :
# 39| mu39_9(ClassWithDestructor2) = Uninitialized[#temp39:7] : &:r39_8
# 39| r39_10(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 39| v39_11(void) = Call[ClassWithDestructor2] : func:r39_10, this:r39_8
# 39| mu39_12(unknown) = ^CallSideEffect : ~m?
# 39| mu39_13(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r39_8
# 39| r39_14(ClassWithDestructor2) = Load[#temp39:7] : &:r39_8, ~m?
# 39| r39_15(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| mu39_16(ClassWithDestructor2) = Store[#temp39:3] : &:r39_15, r39_14
#-----| Goto -> Block 1
# 39| Block 3
# 39| r39_17(glval<ClassWithDestructor2>) = VariableAddress[#temp39:32] :
# 39| mu39_18(ClassWithDestructor2) = Uninitialized[#temp39:32] : &:r39_17
# 39| r39_19(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 39| v39_20(void) = Call[ClassWithDestructor2] : func:r39_19, this:r39_17
# 39| mu39_21(unknown) = ^CallSideEffect : ~m?
# 39| mu39_22(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r39_17
# 39| r39_23(ClassWithDestructor2) = Load[#temp39:32] : &:r39_17, ~m?
# 39| r39_24(glval<ClassWithDestructor2>) = VariableAddress[#temp39:3] :
# 39| mu39_25(ClassWithDestructor2) = Store[#temp39:3] : &:r39_24, r39_23
#-----| Goto -> Block 1
# 42| void temp_test6(bool)
# 42| Block 0
# 42| v42_1(void) = EnterFunction :
# 42| mu42_2(unknown) = AliasedDefinition :
# 42| mu42_3(unknown) = InitializeNonLocal :
# 42| r42_4(glval<bool>) = VariableAddress[b] :
# 42| mu42_5(bool) = InitializeParameter[b] : &:r42_4
# 43| r43_1(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 43| mu43_2(ClassWithDestructor2) = Uninitialized[c] : &:r43_1
# 43| r43_3(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 43| v43_4(void) = Call[ClassWithDestructor2] : func:r43_3, this:r43_1
# 43| mu43_5(unknown) = ^CallSideEffect : ~m?
# 43| mu43_6(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r43_1
# 44| r44_1(glval<bool>) = VariableAddress[b] :
# 44| r44_2(bool) = Load[b] : &:r44_1, ~m?
# 44| v44_3(void) = ConditionalBranch : r44_2
#-----| False -> Block 4
#-----| True -> Block 3
# 42| Block 1
# 42| v42_6(void) = AliasedUse : ~m?
# 42| v42_7(void) = ExitFunction :
# 42| Block 2
# 42| v42_8(void) = Unwind :
#-----| Goto -> Block 1
# 45| Block 3
# 45| r45_1(glval<ClassWithConstructor>) = VariableAddress[#throw45:7] :
# 45| mu45_2(ClassWithConstructor) = Uninitialized[#throw45:7] : &:r45_1
# 45| r45_3(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 45| r45_4(char) = Constant[120] :
# 45| r45_5(glval<ClassWithDestructor2>) = VariableAddress[#temp45:39] :
# 45| mu45_6(ClassWithDestructor2) = Uninitialized[#temp45:39] : &:r45_5
# 45| r45_7(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 45| v45_8(void) = Call[ClassWithDestructor2] : func:r45_7, this:r45_5
# 45| mu45_9(unknown) = ^CallSideEffect : ~m?
# 45| mu45_10(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r45_5
# 45| r45_11(glval<unknown>) = FunctionAddress[get_x] :
# 45| r45_12(char) = Call[get_x] : func:r45_11, this:r45_5
# 45| mu45_13(unknown) = ^CallSideEffect : ~m?
# 45| v45_14(void) = ^IndirectReadSideEffect[-1] : &:r45_5, ~m?
# 45| mu45_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r45_5
# 45| v45_16(void) = Call[ClassWithConstructor] : func:r45_3, this:r45_1, 0:r45_4, 1:r45_12
# 45| mu45_17(unknown) = ^CallSideEffect : ~m?
# 45| mu45_18(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r45_1
# 45| v45_19(void) = ThrowValue : &:r45_1, ~m?
#-----| Exception -> Block 2
# 47| Block 4
# 47| v47_1(void) = NoOp :
# 47| r47_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 47| r47_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
# 47| v47_4(void) = Call[~ClassWithDestructor2] : func:r47_3, this:r47_2
# 47| mu47_5(unknown) = ^CallSideEffect : ~m?
# 47| v47_6(void) = ^IndirectReadSideEffect[-1] : &:r47_2, ~m?
# 47| mu47_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r47_2
# 42| v42_9(void) = ReturnVoid :
#-----| Goto -> Block 1
# 49| void temp_test7(bool)
# 49| Block 0
# 49| v49_1(void) = EnterFunction :
# 49| mu49_2(unknown) = AliasedDefinition :
# 49| mu49_3(unknown) = InitializeNonLocal :
# 49| r49_4(glval<bool>) = VariableAddress[b] :
# 49| mu49_5(bool) = InitializeParameter[b] : &:r49_4
# 50| r50_1(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 50| mu50_2(ClassWithDestructor2) = Uninitialized[c] : &:r50_1
# 50| r50_3(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 50| v50_4(void) = Call[ClassWithDestructor2] : func:r50_3, this:r50_1
# 50| mu50_5(unknown) = ^CallSideEffect : ~m?
# 50| mu50_6(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r50_1
# 51| r51_1(glval<ClassWithDestructor2>) = VariableAddress[#temp51:5] :
# 51| r51_2(glval<bool>) = VariableAddress[b] :
# 51| r51_3(bool) = Load[b] : &:r51_2, ~m?
# 51| v51_4(void) = ConditionalBranch : r51_3
#-----| False -> Block 4
#-----| True -> Block 3
# 49| Block 1
# 49| v49_6(void) = AliasedUse : ~m?
# 49| v49_7(void) = ExitFunction :
# 49| Block 2
# 49| v49_8(void) = Unwind :
#-----| Goto -> Block 1
# 51| Block 3
# 51| r51_5(glval<ClassWithConstructor>) = VariableAddress[#throw51:9] :
# 51| mu51_6(ClassWithConstructor) = Uninitialized[#throw51:9] : &:r51_5
# 51| r51_7(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 51| r51_8(char) = Constant[120] :
# 51| r51_9(glval<ClassWithDestructor2>) = VariableAddress[#temp51:41] :
# 51| mu51_10(ClassWithDestructor2) = Uninitialized[#temp51:41] : &:r51_9
# 51| r51_11(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 51| v51_12(void) = Call[ClassWithDestructor2] : func:r51_11, this:r51_9
# 51| mu51_13(unknown) = ^CallSideEffect : ~m?
# 51| mu51_14(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r51_9
# 51| r51_15(glval<unknown>) = FunctionAddress[get_x] :
# 51| r51_16(char) = Call[get_x] : func:r51_15, this:r51_9
# 51| mu51_17(unknown) = ^CallSideEffect : ~m?
# 51| v51_18(void) = ^IndirectReadSideEffect[-1] : &:r51_9, ~m?
# 51| mu51_19(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r51_9
# 51| v51_20(void) = Call[ClassWithConstructor] : func:r51_7, this:r51_5, 0:r51_8, 1:r51_16
# 51| mu51_21(unknown) = ^CallSideEffect : ~m?
# 51| mu51_22(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r51_5
# 51| v51_23(void) = ThrowValue : &:r51_5, ~m?
#-----| Exception -> Block 2
# 51| Block 4
# 51| r51_24(glval<ClassWithDestructor2>) = VariableAddress[#temp51:75] :
# 51| mu51_25(ClassWithDestructor2) = Uninitialized[#temp51:75] : &:r51_24
# 51| r51_26(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 51| v51_27(void) = Call[ClassWithDestructor2] : func:r51_26, this:r51_24
# 51| mu51_28(unknown) = ^CallSideEffect : ~m?
# 51| mu51_29(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r51_24
# 51| r51_30(ClassWithDestructor2) = Load[#temp51:75] : &:r51_24, ~m?
# 51| r51_31(glval<ClassWithDestructor2>) = VariableAddress[#temp51:5] :
# 51| mu51_32(ClassWithDestructor2) = Store[#temp51:5] : &:r51_31, r51_30
# 51| r51_33(glval<ClassWithDestructor2>) = VariableAddress[#temp51:5] :
# 51| r51_34(ClassWithDestructor2) = Load[#temp51:5] : &:r51_33, ~m?
# 51| mu51_35(ClassWithDestructor2) = Store[#temp51:5] : &:r51_1, r51_34
# 52| v52_1(void) = NoOp :
# 52| r52_2(glval<ClassWithDestructor2>) = VariableAddress[c] :
# 52| r52_3(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
# 52| v52_4(void) = Call[~ClassWithDestructor2] : func:r52_3, this:r52_2
# 52| mu52_5(unknown) = ^CallSideEffect : ~m?
# 52| v52_6(void) = ^IndirectReadSideEffect[-1] : &:r52_2, ~m?
# 52| mu52_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r52_2
# 49| v49_9(void) = ReturnVoid :
#-----| Goto -> Block 1
# 54| void temp_test8(bool)
# 54| Block 0
# 54| v54_1(void) = EnterFunction :
# 54| mu54_2(unknown) = AliasedDefinition :
# 54| mu54_3(unknown) = InitializeNonLocal :
# 54| r54_4(glval<bool>) = VariableAddress[b] :
# 54| mu54_5(bool) = InitializeParameter[b] : &:r54_4
# 55| r55_1(glval<ClassWithDestructor2>) = VariableAddress[#temp55:5] :
# 55| r55_2(glval<bool>) = VariableAddress[b] :
# 55| r55_3(bool) = Load[b] : &:r55_2, ~m?
# 55| v55_4(void) = ConditionalBranch : r55_3
#-----| False -> Block 4
#-----| True -> Block 3
# 54| Block 1
# 54| v54_6(void) = AliasedUse : ~m?
# 54| v54_7(void) = ExitFunction :
# 54| Block 2
# 54| v54_8(void) = Unwind :
#-----| Goto -> Block 1
# 55| Block 3
# 55| r55_5(glval<ClassWithConstructor>) = VariableAddress[#throw55:9] :
# 55| mu55_6(ClassWithConstructor) = Uninitialized[#throw55:9] : &:r55_5
# 55| r55_7(glval<unknown>) = FunctionAddress[ClassWithConstructor] :
# 55| r55_8(char) = Constant[120] :
# 55| r55_9(glval<ClassWithDestructor2>) = VariableAddress[#temp55:41] :
# 55| mu55_10(ClassWithDestructor2) = Uninitialized[#temp55:41] : &:r55_9
# 55| r55_11(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 55| v55_12(void) = Call[ClassWithDestructor2] : func:r55_11, this:r55_9
# 55| mu55_13(unknown) = ^CallSideEffect : ~m?
# 55| mu55_14(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r55_9
# 55| r55_15(glval<unknown>) = FunctionAddress[get_x] :
# 55| r55_16(char) = Call[get_x] : func:r55_15, this:r55_9
# 55| mu55_17(unknown) = ^CallSideEffect : ~m?
# 55| v55_18(void) = ^IndirectReadSideEffect[-1] : &:r55_9, ~m?
# 55| mu55_19(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r55_9
# 55| v55_20(void) = Call[ClassWithConstructor] : func:r55_7, this:r55_5, 0:r55_8, 1:r55_16
# 55| mu55_21(unknown) = ^CallSideEffect : ~m?
# 55| mu55_22(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r55_5
# 55| v55_23(void) = ThrowValue : &:r55_5, ~m?
#-----| Exception -> Block 2
# 55| Block 4
# 55| r55_24(glval<ClassWithDestructor2>) = VariableAddress[#temp55:75] :
# 55| mu55_25(ClassWithDestructor2) = Uninitialized[#temp55:75] : &:r55_24
# 55| r55_26(glval<unknown>) = FunctionAddress[ClassWithDestructor2] :
# 55| v55_27(void) = Call[ClassWithDestructor2] : func:r55_26, this:r55_24
# 55| mu55_28(unknown) = ^CallSideEffect : ~m?
# 55| mu55_29(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r55_24
# 55| r55_30(ClassWithDestructor2) = Load[#temp55:75] : &:r55_24, ~m?
# 55| r55_31(glval<ClassWithDestructor2>) = VariableAddress[#temp55:5] :
# 55| mu55_32(ClassWithDestructor2) = Store[#temp55:5] : &:r55_31, r55_30
# 55| r55_33(glval<ClassWithDestructor2>) = VariableAddress[#temp55:5] :
# 55| r55_34(ClassWithDestructor2) = Load[#temp55:5] : &:r55_33, ~m?
# 55| mu55_35(ClassWithDestructor2) = Store[#temp55:5] : &:r55_1, r55_34
# 56| v56_1(void) = NoOp :
# 54| v54_9(void) = ReturnVoid :
#-----| Goto -> Block 1
ir.c:
# 7| void MyCoordsTest(int)
# 7| Block 0

View File

@@ -11,6 +11,7 @@ edges
| test_free.cpp:128:10:128:11 | pointer to free output argument | test_free.cpp:129:10:129:11 | * ... | provenance | |
| test_free.cpp:152:27:152:27 | pointer to free output argument | test_free.cpp:154:10:154:10 | a | provenance | |
| test_free.cpp:207:10:207:10 | pointer to free output argument | test_free.cpp:209:10:209:10 | a | provenance | |
| test_free.cpp:301:12:301:14 | pointer to g_free output argument | test_free.cpp:302:12:302:14 | buf | provenance | |
nodes
| test_free.cpp:11:10:11:10 | pointer to free output argument | semmle.label | pointer to free output argument |
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
@@ -36,6 +37,8 @@ nodes
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
| test_free.cpp:207:10:207:10 | pointer to free output argument | semmle.label | pointer to free output argument |
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
| test_free.cpp:301:12:301:14 | pointer to g_free output argument | semmle.label | pointer to g_free output argument |
| test_free.cpp:302:12:302:14 | buf | semmle.label | buf |
subpaths
#select
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
@@ -50,3 +53,4 @@ subpaths
| test_free.cpp:129:10:129:11 | * ... | test_free.cpp:128:10:128:11 | pointer to free output argument | test_free.cpp:129:10:129:11 | * ... | Memory pointed to by '* ...' may already have been freed by $@. | test_free.cpp:128:5:128:8 | call to free | call to free |
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | pointer to free output argument | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | pointer to free output argument | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:302:12:302:14 | buf | test_free.cpp:301:12:301:14 | pointer to g_free output argument | test_free.cpp:302:12:302:14 | buf | Memory pointed to by 'buf' may already have been freed by $@. | test_free.cpp:301:5:301:10 | call to g_free | call to g_free |

View File

@@ -102,6 +102,8 @@
| test_free.cpp:282:10:282:12 | buf |
| test_free.cpp:288:8:288:10 | buf |
| test_free.cpp:293:8:293:10 | buf |
| test_free.cpp:301:12:301:14 | buf |
| test_free.cpp:302:12:302:14 | buf |
| virtual.cpp:18:10:18:10 | a |
| virtual.cpp:19:10:19:10 | c |
| virtual.cpp:38:10:38:10 | b |

View File

@@ -293,4 +293,11 @@ void test_free_struct4(char* buf, MyStruct s) {
free(buf);
s.buf = buf;
char c = s.buf[0]; // BAD
}
void g_free (void*);
void test_g_free(char* buf) {
g_free(buf);
g_free(buf); // BAD
}

View File

@@ -101,6 +101,10 @@ edges
| test.cpp:857:16:857:29 | ... + ... | test.cpp:857:16:857:29 | ... + ... | provenance | |
| test.cpp:857:16:857:29 | ... + ... | test.cpp:860:5:860:11 | ... = ... | provenance | |
| test.cpp:857:16:857:29 | ... + ... | test.cpp:860:5:860:11 | ... = ... | provenance | |
| test.cpp:868:15:868:35 | call to g_malloc | test.cpp:869:15:869:22 | ... + ... | provenance | |
| test.cpp:869:15:869:22 | ... + ... | test.cpp:869:15:869:22 | ... + ... | provenance | |
| test.cpp:869:15:869:22 | ... + ... | test.cpp:870:14:870:15 | * ... | provenance | |
| test.cpp:869:15:869:22 | ... + ... | test.cpp:870:14:870:15 | * ... | provenance | |
nodes
| test.cpp:4:15:4:33 | call to malloc | semmle.label | call to malloc |
| test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... |
@@ -198,6 +202,10 @@ nodes
| test.cpp:857:16:857:29 | ... + ... | semmle.label | ... + ... |
| test.cpp:857:16:857:29 | ... + ... | semmle.label | ... + ... |
| test.cpp:860:5:860:11 | ... = ... | semmle.label | ... = ... |
| test.cpp:868:15:868:35 | call to g_malloc | semmle.label | call to g_malloc |
| test.cpp:869:15:869:22 | ... + ... | semmle.label | ... + ... |
| test.cpp:869:15:869:22 | ... + ... | semmle.label | ... + ... |
| test.cpp:870:14:870:15 | * ... | semmle.label | * ... |
subpaths
#select
| test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:33 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:33 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -231,3 +239,4 @@ subpaths
| test.cpp:842:3:842:20 | ... = ... | test.cpp:841:18:841:35 | call to malloc | test.cpp:842:3:842:20 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:841:18:841:35 | call to malloc | call to malloc | test.cpp:842:11:842:15 | index | index |
| test.cpp:849:5:849:22 | ... = ... | test.cpp:848:20:848:37 | call to malloc | test.cpp:849:5:849:22 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:848:20:848:37 | call to malloc | call to malloc | test.cpp:849:13:849:17 | index | index |
| test.cpp:860:5:860:11 | ... = ... | test.cpp:856:12:856:35 | call to malloc | test.cpp:860:5:860:11 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:856:12:856:35 | call to malloc | call to malloc | test.cpp:857:21:857:28 | ... + ... | ... + ... |
| test.cpp:870:14:870:15 | * ... | test.cpp:868:15:868:35 | call to g_malloc | test.cpp:870:14:870:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:868:15:868:35 | call to g_malloc | call to g_malloc | test.cpp:869:19:869:22 | size | size |

View File

@@ -859,4 +859,13 @@ void test_regression(size_t size) {
if(p <= chend) {
*p = 42; // $ deref=L857->L860 // BAD
}
}
void* g_malloc(size_t size);
void test17(int size) {
char* p = (char*)g_malloc(size);
char* q = p + size; // $ alloc=L868
char a = *q; // $ deref=L869->L870 // BAD
}

View File

@@ -0,0 +1,74 @@
edges
| test.cpp:17:13:17:18 | new | test.cpp:18:21:18:47 | p | provenance | |
| test.cpp:22:13:22:26 | new | test.cpp:23:12:23:30 | p | provenance | |
| test.cpp:27:13:27:18 | new | test.cpp:28:25:28:55 | p | provenance | |
| test.cpp:32:13:32:30 | new | test.cpp:33:12:33:30 | p | provenance | |
| test.cpp:47:21:47:36 | new | test.cpp:48:22:48:55 | p | provenance | |
| test.cpp:66:15:66:21 | new | test.cpp:67:12:67:31 | a | provenance | |
| test.cpp:76:15:76:21 | new | test.cpp:77:12:77:31 | a | provenance | |
| test.cpp:83:9:83:15 | new | test.cpp:88:14:88:33 | a | provenance | |
| test.cpp:85:9:85:15 | new | test.cpp:88:14:88:33 | a | provenance | |
| test.cpp:115:12:115:17 | new | test.cpp:116:20:116:51 | s2 | provenance | |
| test.cpp:127:12:127:17 | new | test.cpp:128:24:128:59 | s2 | provenance | |
| test.cpp:140:12:140:17 | new | test.cpp:141:23:141:57 | s1 | provenance | |
| test.cpp:143:14:143:19 | new | test.cpp:145:28:145:68 | s1_2 | provenance | |
| test.cpp:153:9:153:15 | new | test.cpp:159:14:159:33 | a | provenance | |
| test.cpp:166:9:166:15 | new | test.cpp:171:14:171:33 | a | provenance | |
| test.cpp:168:9:168:15 | new | test.cpp:171:14:171:33 | a | provenance | |
| test.cpp:179:15:179:24 | new | test.cpp:181:15:181:25 | u64 | provenance | |
| test.cpp:187:15:187:24 | new | test.cpp:189:25:189:45 | u64 | provenance | |
| test.cpp:207:14:207:26 | new | test.cpp:209:17:209:28 | si | provenance | |
| test.cpp:217:13:217:18 | new | test.cpp:218:30:218:65 | p | provenance | |
| test.cpp:226:13:226:18 | new | test.cpp:227:29:227:63 | p | provenance | |
nodes
| test.cpp:17:13:17:18 | new | semmle.label | new |
| test.cpp:18:21:18:47 | p | semmle.label | p |
| test.cpp:22:13:22:26 | new | semmle.label | new |
| test.cpp:23:12:23:30 | p | semmle.label | p |
| test.cpp:27:13:27:18 | new | semmle.label | new |
| test.cpp:28:25:28:55 | p | semmle.label | p |
| test.cpp:32:13:32:30 | new | semmle.label | new |
| test.cpp:33:12:33:30 | p | semmle.label | p |
| test.cpp:47:21:47:36 | new | semmle.label | new |
| test.cpp:48:22:48:55 | p | semmle.label | p |
| test.cpp:66:15:66:21 | new | semmle.label | new |
| test.cpp:67:12:67:31 | a | semmle.label | a |
| test.cpp:76:15:76:21 | new | semmle.label | new |
| test.cpp:77:12:77:31 | a | semmle.label | a |
| test.cpp:83:9:83:15 | new | semmle.label | new |
| test.cpp:85:9:85:15 | new | semmle.label | new |
| test.cpp:88:14:88:33 | a | semmle.label | a |
| test.cpp:115:12:115:17 | new | semmle.label | new |
| test.cpp:116:20:116:51 | s2 | semmle.label | s2 |
| test.cpp:127:12:127:17 | new | semmle.label | new |
| test.cpp:128:24:128:59 | s2 | semmle.label | s2 |
| test.cpp:140:12:140:17 | new | semmle.label | new |
| test.cpp:141:23:141:57 | s1 | semmle.label | s1 |
| test.cpp:143:14:143:19 | new | semmle.label | new |
| test.cpp:145:28:145:68 | s1_2 | semmle.label | s1_2 |
| test.cpp:153:9:153:15 | new | semmle.label | new |
| test.cpp:159:14:159:33 | a | semmle.label | a |
| test.cpp:166:9:166:15 | new | semmle.label | new |
| test.cpp:168:9:168:15 | new | semmle.label | new |
| test.cpp:171:14:171:33 | a | semmle.label | a |
| test.cpp:179:15:179:24 | new | semmle.label | new |
| test.cpp:181:15:181:25 | u64 | semmle.label | u64 |
| test.cpp:187:15:187:24 | new | semmle.label | new |
| test.cpp:189:25:189:45 | u64 | semmle.label | u64 |
| test.cpp:207:14:207:26 | new | semmle.label | new |
| test.cpp:209:17:209:28 | si | semmle.label | si |
| test.cpp:217:13:217:18 | new | semmle.label | new |
| test.cpp:218:30:218:65 | p | semmle.label | p |
| test.cpp:226:13:226:18 | new | semmle.label | new |
| test.cpp:227:29:227:63 | p | semmle.label | p |
subpaths
#select
| test.cpp:28:25:28:55 | p | test.cpp:27:13:27:18 | new | test.cpp:28:25:28:55 | p | Conversion from $@ to $@ is invalid. | test.cpp:1:8:1:9 | S1 | S1 | test.cpp:11:8:11:21 | Not_S1_wrapper | Not_S1_wrapper |
| test.cpp:33:12:33:30 | p | test.cpp:32:13:32:30 | new | test.cpp:33:12:33:30 | p | Conversion from $@ to $@ is invalid. | test.cpp:11:8:11:21 | Not_S1_wrapper | Not_S1_wrapper | test.cpp:1:8:1:9 | S1 | S1 |
| test.cpp:67:12:67:31 | a | test.cpp:66:15:66:21 | new | test.cpp:67:12:67:31 | a | Conversion from $@ to $@ is invalid. | test.cpp:55:8:55:10 | Cat | Cat | test.cpp:60:8:60:10 | Dog | Dog |
| test.cpp:128:24:128:59 | s2 | test.cpp:127:12:127:17 | new | test.cpp:128:24:128:59 | s2 | Conversion from $@ to $@ is invalid. | test.cpp:102:8:102:9 | S2 | S2 | test.cpp:119:8:119:20 | Not_S2_prefix | Not_S2_prefix |
| test.cpp:145:28:145:68 | s1_2 | test.cpp:143:14:143:19 | new | test.cpp:145:28:145:68 | s1_2 | Conversion from $@ to $@ is invalid. | test.cpp:1:8:1:9 | S1 | S1 | test.cpp:131:8:131:23 | HasSomeBitFields | HasSomeBitFields |
| test.cpp:159:14:159:33 | a | test.cpp:153:9:153:15 | new | test.cpp:159:14:159:33 | a | Conversion from $@ to $@ is invalid. | test.cpp:60:8:60:10 | Dog | Dog | test.cpp:55:8:55:10 | Cat | Cat |
| test.cpp:189:25:189:45 | u64 | test.cpp:187:15:187:24 | new | test.cpp:189:25:189:45 | u64 | Conversion from $@ to $@ is invalid. | test.cpp:175:8:175:13 | UInt64 | UInt64 | test.cpp:184:8:184:22 | UInt8_with_more | UInt8_with_more |
| test.cpp:218:30:218:65 | p | test.cpp:217:13:217:18 | new | test.cpp:218:30:218:65 | p | Conversion from $@ to $@ is invalid. | test.cpp:1:8:1:9 | S1 | S1 | test.cpp:212:8:212:26 | UnrelatedStructSize | UnrelatedStructSize |
| test.cpp:227:29:227:63 | p | test.cpp:226:13:226:18 | new | test.cpp:227:29:227:63 | p | Conversion from $@ to $@ is invalid. | test.cpp:1:8:1:9 | S1 | S1 | test.cpp:221:8:221:25 | TooLargeBufferSize | TooLargeBufferSize |

View File

@@ -0,0 +1 @@
Security/CWE/CWE-843/TypeConfusion.ql

View File

@@ -0,0 +1,230 @@
struct S1 {
int a;
void* b;
unsigned char c;
};
struct S1_wrapper {
S1 s1;
};
struct Not_S1_wrapper {
unsigned char x;
S1 s1;
};
void test1() {
void* p = new S1;
S1_wrapper* s1w = static_cast<S1_wrapper*>(p); // GOOD
}
void test2() {
void* p = new S1_wrapper;
S1* s1 = static_cast<S1*>(p); // GOOD
}
void test3() {
void* p = new S1;
Not_S1_wrapper* s1w = static_cast<Not_S1_wrapper*>(p); // BAD
}
void test4() {
void* p = new Not_S1_wrapper;
S1* s1 = static_cast<S1*>(p); // BAD
}
struct HasBitFields {
int x : 16;
int y : 16;
int z : 32;
};
struct BufferStruct {
unsigned char buffer[sizeof(HasBitFields)];
};
void test5() {
HasBitFields* p = new HasBitFields;
BufferStruct* bs = reinterpret_cast<BufferStruct*>(p); // GOOD
}
struct Animal {
virtual ~Animal();
};
struct Cat : public Animal {
Cat();
~Cat();
};
struct Dog : public Animal {
Dog();
~Dog();
};
void test6() {
Animal* a = new Cat;
Dog* d = static_cast<Dog*>(a); // BAD
}
void test7() {
Animal* a = new Cat;
Dog* d = dynamic_cast<Dog*>(a); // GOOD
}
void test8() {
Animal* a = new Cat;
Cat* d = static_cast<Cat*>(a); // GOOD
}
void test9(bool b) {
Animal* a;
if(b) {
a = new Cat;
} else {
a = new Dog;
}
if(b) {
Cat* d = static_cast<Cat*>(a); // GOOD
}
}
/**
* The layout of S2 is:
* 0: int
* 8: void*
* 16: unsigned char
* 16 + pad: unsigned char
* 32 + pad: int
* 40 + pad: void*
* 48 + pad: unsigned char
*/
struct S2 {
S1 s1;
unsigned char buffer[16];
S1 s1_2;
};
struct S2_prefix {
int a;
void* p;
unsigned char c;
};
void test10() {
S2* s2 = new S2;
S2_prefix* s2p = reinterpret_cast<S2_prefix*>(s2); // GOOD
}
struct Not_S2_prefix {
int a;
void* p;
void* p2;
unsigned char c;
};
void test11() {
S2* s2 = new S2;
Not_S2_prefix* s2p = reinterpret_cast<Not_S2_prefix*>(s2); // BAD
}
struct HasSomeBitFields {
int x : 16;
int y;
int z : 32;
};
void test12() {
// This has doesn't have any non-bitfield member, so we don't detect
// the problem here since the query currently ignores bitfields.
S1* s1 = new S1;
HasBitFields* hbf = reinterpret_cast<HasBitFields*>(s1); // BAD [NOT DETECTED]
S1* s1_2 = new S1;
// This one has a non-bitfield members. So we detect the problem
HasSomeBitFields* hbf2 = reinterpret_cast<HasSomeBitFields*>(s1_2); // BAD
}
void test13(bool b, Cat* c) {
Animal* a;
if(b) {
a = c;
} else {
a = new Dog;
}
// This FP happens despite the `not GoodFlow::flowTo(sinkNode)` condition in the query
// because we don't find a flow path from `a = c` to `static_cast<Cat*>(a)` because
// the "source" (i.e., `a = c`) doesn't have an allocation.
if(b) {
Cat* d = static_cast<Cat*>(a); // GOOD [FALSE POSITIVE]
}
}
void test14(bool b) {
Animal* a;
if(b) {
a = new Cat;
} else {
a = new Dog;
}
if(!b) {
Cat* d = static_cast<Cat*>(a); // BAD [NOT DETECTED]
}
}
struct UInt64 { unsigned long u64; };
struct UInt8 { unsigned char u8; };
void test14() {
void* u64 = new UInt64;
// ...
UInt8* u8 = (UInt8*)u64; // GOOD
}
struct UInt8_with_more { UInt8 u8; void* p; };
void test15() {
void* u64 = new UInt64;
// ...
UInt8_with_more* u8 = (UInt8_with_more*)u64; // BAD
}
struct SingleInt {
int i;
} __attribute__((packed));;
struct PairInts {
int x, y;
} __attribute__((packed));;
union MyUnion
{
PairInts p;
unsigned long long foo;
} __attribute__((packed));
void test16() {
void* si = new SingleInt;
// ...
MyUnion* mu = (MyUnion*)si; // BAD [NOT DETECTED]
}
struct UnrelatedStructSize {
unsigned char buffer[1024];
};
void test17() {
void* p = new S1;
UnrelatedStructSize* uss = static_cast<UnrelatedStructSize*>(p); // BAD
}
struct TooLargeBufferSize {
unsigned char buffer[sizeof(S1) + 1];
};
void test18() {
void* p = new S1;
TooLargeBufferSize* uss = static_cast<TooLargeBufferSize*>(p); // BAD
}
// semmle-extractor-options: --gcc -std=c++11

View File

@@ -268,6 +268,5 @@ csharp_style_var_elsewhere = true:suggestion
#
[extractor/Semmle.Extraction/Tuples.cs,
extractor/Semmle.Extraction.CSharp/Tuples.cs,
extractor/Semmle.Extraction.CIL/Tuples.cs]
dotnet_naming_rule.members_should_be_pascal_case.severity = none
extractor/Semmle.Extraction.CSharp/Tuples.cs]
dotnet_naming_rule.members_should_be_pascal_case.severity = none

View File

@@ -8,8 +8,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction", "extrac
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp", "extractor\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj", "{C4D62DA0-B64B-440B-86DC-AB52318CB8BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL", "extractor\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj", "{399A1579-68F0-40F4-9A23-F241BA697F9C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.DependencyFetching", "extractor\Semmle.Extraction.CSharp.DependencyFetching\Semmle.Extraction.CSharp.DependencyFetching.csproj", "{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Standalone", "extractor\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj", "{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}"
@@ -18,8 +16,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.St
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Util", "extractor\Semmle.Extraction.CSharp.Util\Semmle.Extraction.CSharp.Util.csproj", "{998A0D4C-8BFC-4513-A28D-4816AFB89882}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL.Driver", "extractor\Semmle.Extraction.CIL.Driver\Semmle.Extraction.CIL.Driver.csproj", "{EFA400B3-C1CE-446F-A4E2-8B44E61EF47C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Driver", "extractor\Semmle.Extraction.CSharp.Driver\Semmle.Extraction.CSharp.Driver.csproj", "{C36453BF-0C82-448A-B15D-26947503A2D3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.Tests", "extractor\Semmle.Extraction.Tests\Semmle.Extraction.Tests.csproj", "{CD8D3F90-AD2E-4BB5-8E82-B94AA293864A}"

View File

@@ -47,13 +47,6 @@ options:
the code (for example if it uses inaccessible dependencies).
type: string
pattern: "^(false|true)$"
cil:
title: Whether to enable CIL extraction.
description: >
A value indicating, whether CIL extraction should be enabled.
The default is 'true'.
type: string
pattern: "^(false|true)$"
logging:
title: Options pertaining to logging.
type: object

View File

@@ -1,44 +1,44 @@
package,sink,source,summary,sink:code-injection,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:file-content-store,sink:html-injection,sink:js-injection,sink:log-injection,sink:sql-injection,source:commandargs,source:environment,source:file,source:file-write,source:local,source:remote,summary:taint,summary:value
Amazon.Lambda.APIGatewayEvents,,6,,,,,,,,,,,,,,,,,6,,
Amazon.Lambda.Core,10,,,,,,,,,,,10,,,,,,,,,
Dapper,55,,,,,,,,,,,,55,,,,,,,,
ILCompiler,,,81,,,,,,,,,,,,,,,,,81,
ILLink.RoslynAnalyzer,,,63,,,,,,,,,,,,,,,,,63,
ILLink.Shared,,,32,,,,,,,,,,,,,,,,,29,3
ILLink.Tasks,,,5,,,,,,,,,,,,,,,,,5,
Internal.IL,,,69,,,,,,,,,,,,,,,,,67,2
Internal.Pgo,,,9,,,,,,,,,,,,,,,,,8,1
Internal.TypeSystem,,,367,,,,,,,,,,,,,,,,,331,36
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,,,,7,
Microsoft.Android.Build,,,14,,,,,,,,,,,,,,,,,14,
Microsoft.Apple.Build,,,7,,,,,,,,,,,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,
Microsoft.CSharp,,,24,,,,,,,,,,,,,,,,,24,
Microsoft.Diagnostics.Tools.Pgo,,,13,,,,,,,,,,,,,,,,,13,
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,12
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,,,,15,
Microsoft.Extensions.Caching.Memory,,,38,,,,,,,,,,,,,,,,,37,1
Microsoft.Extensions.Configuration,,2,89,,,,,,,,,,,,2,,,,,86,3
Microsoft.Extensions.DependencyInjection,,,120,,,,,,,,,,,,,,,,,120,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,,,,12,
Microsoft.Extensions.Diagnostics.Metrics,,,13,,,,,,,,,,,,,,,,,13,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,,,,,,15,
Microsoft.Extensions.FileSystemGlobbing,,,16,,,,,,,,,,,,,,,,,14,2
Microsoft.Extensions.Hosting,,,23,,,,,,,,,,,,,,,,,22,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,,,,10,
Microsoft.Extensions.Logging,,,60,,,,,,,,,,,,,,,,,59,1
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,,,,8,
Microsoft.Extensions.Primitives,,,64,,,,,,,,,,,,,,,,,64,
Microsoft.Interop,,,78,,,,,,,,,,,,,,,,,78,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,,,,1,
Microsoft.NET.WebAssembly.Webcil,,,7,,,,,,,,,,,,,,,,,7,
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,,,,5,5
Microsoft.WebAssembly.Build.Tasks,,,3,,,,,,,,,,,,,,,,,3,
Microsoft.Win32.SafeHandles,,,4,,,,,,,,,,,,,,,,,4,
Mono.Linker,,,163,,,,,,,,,,,,,,,,,163,
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,7,
SourceGenerators,,,4,,,,,,,,,,,,,,,,,4,
System,67,30,11864,,8,8,9,,,4,5,,33,2,3,1,17,3,4,9898,1966
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,
package,sink,source,summary,sink:code-injection,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:file-content-store,sink:html-injection,sink:js-injection,sink:log-injection,sink:sql-injection,source:commandargs,source:environment,source:file,source:file-write,source:local,source:remote,source:windows-registry,summary:taint,summary:value
Amazon.Lambda.APIGatewayEvents,,6,,,,,,,,,,,,,,,,,6,,,
Amazon.Lambda.Core,10,,,,,,,,,,,10,,,,,,,,,,
Dapper,55,,,,,,,,,,,,55,,,,,,,,,
ILCompiler,,,81,,,,,,,,,,,,,,,,,,81,
ILLink.RoslynAnalyzer,,,63,,,,,,,,,,,,,,,,,,63,
ILLink.Shared,,,32,,,,,,,,,,,,,,,,,,29,3
ILLink.Tasks,,,5,,,,,,,,,,,,,,,,,,5,
Internal.IL,,,69,,,,,,,,,,,,,,,,,,67,2
Internal.Pgo,,,9,,,,,,,,,,,,,,,,,,8,1
Internal.TypeSystem,,,367,,,,,,,,,,,,,,,,,,331,36
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,,,,,7,
Microsoft.Android.Build,,,14,,,,,,,,,,,,,,,,,,14,
Microsoft.Apple.Build,,,7,,,,,,,,,,,,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,,
Microsoft.CSharp,,,24,,,,,,,,,,,,,,,,,,24,
Microsoft.Diagnostics.Tools.Pgo,,,13,,,,,,,,,,,,,,,,,,13,
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,,12
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,,,,,15,
Microsoft.Extensions.Caching.Memory,,,38,,,,,,,,,,,,,,,,,,37,1
Microsoft.Extensions.Configuration,,2,89,,,,,,,,,,,,2,,,,,,86,3
Microsoft.Extensions.DependencyInjection,,,120,,,,,,,,,,,,,,,,,,120,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,,,,,12,
Microsoft.Extensions.Diagnostics.Metrics,,,13,,,,,,,,,,,,,,,,,,13,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,,,,,,,15,
Microsoft.Extensions.FileSystemGlobbing,,,16,,,,,,,,,,,,,,,,,,14,2
Microsoft.Extensions.Hosting,,,23,,,,,,,,,,,,,,,,,,22,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,,,,,10,
Microsoft.Extensions.Logging,,,60,,,,,,,,,,,,,,,,,,59,1
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,,,,,8,
Microsoft.Extensions.Primitives,,,64,,,,,,,,,,,,,,,,,,64,
Microsoft.Interop,,,78,,,,,,,,,,,,,,,,,,78,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,,,,,1,
Microsoft.NET.WebAssembly.Webcil,,,7,,,,,,,,,,,,,,,,,,7,
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,,,,,5,5
Microsoft.WebAssembly.Build.Tasks,,,3,,,,,,,,,,,,,,,,,,3,
Microsoft.Win32,,4,4,,,,,,,,,,,,,,,,,4,4,
Mono.Linker,,,163,,,,,,,,,,,,,,,,,,163,
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,,7,
SourceGenerators,,,4,,,,,,,,,,,,,,,,,,4,
System,67,30,11864,,8,8,9,,,4,5,,33,2,3,1,17,3,4,,9898,1966
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,,
1 package sink source summary sink:code-injection sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:file-content-store sink:html-injection sink:js-injection sink:log-injection sink:sql-injection source:commandargs source:environment source:file source:file-write source:local source:remote source:windows-registry summary:taint summary:value
2 Amazon.Lambda.APIGatewayEvents 6 6
3 Amazon.Lambda.Core 10 10
4 Dapper 55 55
5 ILCompiler 81 81
6 ILLink.RoslynAnalyzer 63 63
7 ILLink.Shared 32 29 3
8 ILLink.Tasks 5 5
9 Internal.IL 69 67 2
10 Internal.Pgo 9 8 1
11 Internal.TypeSystem 367 331 36
12 JsonToItemsTaskFactory 7 7
13 Microsoft.Android.Build 14 14
14 Microsoft.Apple.Build 7 7
15 Microsoft.ApplicationBlocks.Data 28 28
16 Microsoft.CSharp 24 24
17 Microsoft.Diagnostics.Tools.Pgo 13 13
18 Microsoft.EntityFrameworkCore 6 12 6 12
19 Microsoft.Extensions.Caching.Distributed 15 15
20 Microsoft.Extensions.Caching.Memory 38 37 1
21 Microsoft.Extensions.Configuration 2 89 2 86 3
22 Microsoft.Extensions.DependencyInjection 120 120
23 Microsoft.Extensions.DependencyModel 12 12
24 Microsoft.Extensions.Diagnostics.Metrics 13 13
25 Microsoft.Extensions.FileProviders 15 15
26 Microsoft.Extensions.FileSystemGlobbing 16 14 2
27 Microsoft.Extensions.Hosting 23 22 1
28 Microsoft.Extensions.Http 10 10
29 Microsoft.Extensions.Logging 60 59 1
30 Microsoft.Extensions.Options 8 8
31 Microsoft.Extensions.Primitives 64 64
32 Microsoft.Interop 78 78
33 Microsoft.NET.Build.Tasks 1 1
34 Microsoft.NET.WebAssembly.Webcil 7 7
35 Microsoft.VisualBasic 10 5 5
36 Microsoft.WebAssembly.Build.Tasks 3 3
37 Microsoft.Win32.SafeHandles Microsoft.Win32 4 4 4 4
38 Mono.Linker 163 163
39 MySql.Data.MySqlClient 48 48
40 Newtonsoft.Json 91 73 18
41 ServiceStack 194 7 27 75 92 7
42 SourceGenerators 4 4
43 System 67 30 11864 8 8 9 4 5 33 2 3 1 17 3 4 9898 1966
44 Windows.Security.Cryptography.Core 1 1

View File

@@ -9,6 +9,6 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",30,11864,67,9
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32.SafeHandles``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",8,1547,148,
Totals,,38,13418,409,9
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",12,1547,148,
Totals,,42,13418,409,9

View File

@@ -1,250 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Driver
{
/// <summary>
/// Information about a single assembly.
/// In particular, provides references between assemblies.
/// </summary>
internal class AssemblyInfo
{
public override string ToString() => Filename;
private static AssemblyName CreateAssemblyName(MetadataReader mdReader, StringHandle name, System.Version version, StringHandle culture)
{
var cultureString = mdReader.GetString(culture);
var assemblyName = new AssemblyName()
{
Name = mdReader.GetString(name),
Version = version
};
if (cultureString != "neutral")
assemblyName.CultureInfo = CultureInfo.GetCultureInfo(cultureString);
return assemblyName;
}
private static AssemblyName CreateAssemblyName(MetadataReader mdReader, AssemblyReference ar)
{
var an = CreateAssemblyName(mdReader, ar.Name, ar.Version, ar.Culture);
if (!ar.PublicKeyOrToken.IsNil)
an.SetPublicKeyToken(mdReader.GetBlobBytes(ar.PublicKeyOrToken));
return an;
}
private static AssemblyName CreateAssemblyName(MetadataReader mdReader, AssemblyDefinition ad)
{
var an = CreateAssemblyName(mdReader, ad.Name, ad.Version, ad.Culture);
if (!ad.PublicKey.IsNil)
an.SetPublicKey(mdReader.GetBlobBytes(ad.PublicKey));
return an;
}
/// <summary>
/// Initializes a new instance of the <see cref="AssemblyInfo"/> class.
/// </summary>
/// <param name="path">Path of the assembly.</param>
/// <exception cref="Semmle.Extraction.CIL.Driver.InvalidAssemblyException">
/// Thrown when the input file is not a valid assembly.
/// </exception>
public AssemblyInfo(string path)
{
Filename = path;
// Attempt to open the file and see if it's a valid assembly.
using var stream = File.OpenRead(path);
using var peReader = new PEReader(stream);
try
{
if (!peReader.HasMetadata)
throw new InvalidAssemblyException();
var mdReader = peReader.GetMetadataReader();
if (!mdReader.IsAssembly)
throw new InvalidAssemblyException();
// Get our own assembly name
Name = CreateAssemblyName(mdReader, mdReader.GetAssemblyDefinition());
References = mdReader.AssemblyReferences
.Select(r => mdReader.GetAssemblyReference(r))
.Select(ar => CreateAssemblyName(mdReader, ar))
.ToArray();
}
catch (System.BadImageFormatException)
{
// This failed on one of the Roslyn tests that includes
// a deliberately malformed assembly.
// In this case, we just skip the extraction of this assembly.
throw new InvalidAssemblyException();
}
}
public AssemblyName Name { get; }
public string Filename { get; }
public bool Extract { get; set; }
public AssemblyName[] References { get; }
}
/// <summary>
/// Helper to manage a collection of assemblies.
/// Resolves references between assemblies and determines which
/// additional assemblies need to be extracted.
/// </summary>
internal class AssemblyList
{
private class AssemblyNameComparer : IEqualityComparer<AssemblyName>
{
bool IEqualityComparer<AssemblyName>.Equals(AssemblyName? x, AssemblyName? y) =>
object.ReferenceEquals(x, y) ||
x?.Name == y?.Name && x?.Version == y?.Version;
int IEqualityComparer<AssemblyName>.GetHashCode(AssemblyName obj) =>
(obj.Name, obj.Version).GetHashCode();
}
private readonly Dictionary<AssemblyName, AssemblyInfo> assembliesRead = new Dictionary<AssemblyName, AssemblyInfo>(new AssemblyNameComparer());
public void AddFile(string assemblyPath, bool extractAll)
{
if (!filesAnalyzed.Contains(assemblyPath))
{
filesAnalyzed.Add(assemblyPath);
try
{
var info = new AssemblyInfo(assemblyPath)
{
Extract = extractAll
};
if (!assembliesRead.ContainsKey(info.Name))
assembliesRead.Add(info.Name, info);
}
catch (InvalidAssemblyException)
{ }
}
}
public IEnumerable<AssemblyInfo> AssembliesToExtract => assembliesRead.Values.Where(info => info.Extract);
private IEnumerable<AssemblyName> AssembliesToReference => AssembliesToExtract.SelectMany(info => info.References);
public void ResolveReferences()
{
var assembliesToReference = new Stack<AssemblyName>(AssembliesToReference);
while (assembliesToReference.Any())
{
var item = assembliesToReference.Pop();
if (assembliesRead.TryGetValue(item, out var info))
{
if (!info.Extract)
{
info.Extract = true;
foreach (var reference in info.References)
assembliesToReference.Push(reference);
}
}
else
{
MissingReferences.Add(item);
}
}
}
private readonly HashSet<string> filesAnalyzed = new HashSet<string>();
public HashSet<AssemblyName> MissingReferences { get; } = new HashSet<AssemblyName>();
}
/// <summary>
/// Parses the command line and collates a list of DLLs/EXEs to extract.
/// </summary>
internal class ExtractorOptions : CommonOptions
{
private readonly AssemblyList assemblyList = new AssemblyList();
public ExtractorOptions(string[] args)
{
this.ParseArguments(args.Append("--pdb").ToArray());
AddFrameworkDirectories(false);
assemblyList.ResolveReferences();
AssembliesToExtract = assemblyList.AssembliesToExtract.ToArray();
}
public void AddDirectory(string directory, bool extractAll)
{
foreach (var file in
Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories).
Concat(Directory.EnumerateFiles(directory, "*.exe", SearchOption.AllDirectories)))
{
assemblyList.AddFile(file, extractAll);
}
}
private void AddFrameworkDirectories(bool extractAll)
{
AddDirectory(RuntimeEnvironment.GetRuntimeDirectory(), extractAll);
}
private void AddFileOrDirectory(string path)
{
path = Path.GetFullPath(path);
if (File.Exists(path))
{
assemblyList.AddFile(path, true);
var directory = Path.GetDirectoryName(path);
if (directory is null)
{
throw new InternalError($"Directory of path '{path}' is null");
}
AddDirectory(directory, false);
}
else if (Directory.Exists(path))
{
AddDirectory(path, true);
}
}
public IEnumerable<AssemblyInfo> AssembliesToExtract { get; }
/// <summary>
/// Gets the assemblies that were referenced but were not available to be
/// extracted. This is not an error, it just means that the database is not
/// as complete as it could be.
/// </summary>
public IEnumerable<AssemblyName> MissingReferences => assemblyList.MissingReferences;
public override bool HandleFlag(string flag, bool value)
{
switch (flag)
{
case "dotnet":
if (value)
AddFrameworkDirectories(true);
return true;
default:
return base.HandleFlag(flag, value);
}
}
public override bool HandleArgument(string argument)
{
AddFileOrDirectory(argument);
return true;
}
public override void InvalidArgument(string argument) { }
}
}

View File

@@ -1,7 +0,0 @@
using System;
namespace Semmle.Extraction.CIL.Driver
{
public class InvalidAssemblyException : Exception
{ }
}

View File

@@ -1,64 +0,0 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CIL.Driver
{
public static class Program
{
private static void DisplayHelp()
{
Console.WriteLine("CIL command line extractor");
Console.WriteLine();
Console.WriteLine("Usage: Semmle.Extraction.CIL.Driver.exe [options] path ...");
Console.WriteLine(" --verbose Turn on verbose output");
Console.WriteLine(" --dotnet Extract the .Net Framework");
Console.WriteLine(" --nocache Overwrite existing trap files");
Console.WriteLine(" --no-pdb Do not extract PDB files");
Console.WriteLine(" path A directory/dll/exe to analyze");
}
private static void ExtractAssembly(string assemblyPath, ILogger logger, CommonOptions options)
{
var sw = new Stopwatch();
sw.Start();
Analyser.ExtractCIL(assemblyPath, logger, options, out _, out _);
sw.Stop();
logger.Log(Severity.Info, " {0} ({1})", assemblyPath, sw.Elapsed);
}
public static void Main(string[] args)
{
if (args.Length == 0)
{
DisplayHelp();
return;
}
var options = new ExtractorOptions(args);
using ILogger logger = new ConsoleLogger(options.Verbosity, logThreadId: false);
var actions = options.AssembliesToExtract
.Select(asm => asm.Filename)
.Select<string, Action>(filename => () => ExtractAssembly(filename, logger, options))
.ToArray();
foreach (var missingRef in options.MissingReferences)
logger.LogInfo(" Missing assembly " + missingRef);
var sw = new Stopwatch();
sw.Start();
var piOptions = new ParallelOptions
{
MaxDegreeOfParallelism = options.Threads
};
Parallel.Invoke(piOptions, actions);
sw.Stop();
logger.Log(Severity.Info, "Extraction completed in {0}", sw.Elapsed);
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Semmle.Extraction.CIL.Driver")]
[assembly: AssemblyDescription("Semmle CIL extractor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Semmle Ltd")]
[assembly: AssemblyProduct("Semmle.Extraction.CIL.Driver")]
[assembly: AssemblyCopyright("Copyright © Semmle 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("5642ae68-9c26-43c9-bd3c-49923dddf02d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CIL.Driver</AssemblyName>
<RootNamespace>Semmle.Extraction.CIL.Driver</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj" />
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,52 +0,0 @@
using System;
using Semmle.Util;
using Semmle.Util.Logging;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL
{
public static class Analyser
{
private static void ExtractCIL(TracingExtractor extractor, TrapWriter trapWriter, bool extractPdbs)
{
using var cilContext = new Context(extractor, trapWriter, extractor.OutputPath, extractPdbs);
cilContext.Populate(new Assembly(cilContext));
cilContext.PopulateAll();
}
/// <summary>
/// Main entry point to the CIL extractor.
/// Call this to extract a given assembly.
/// </summary>
/// <param name="layout">The trap layout.</param>
/// <param name="assemblyPath">The full path of the assembly to extract.</param>
/// <param name="logger">The logger.</param>
/// <param name="nocache">True to overwrite existing trap file.</param>
/// <param name="extractPdbs">Whether to extract PDBs.</param>
/// <param name="trapFile">The path of the trap file.</param>
/// <param name="extracted">Whether the file was extracted (false=cached).</param>
public static void ExtractCIL(string assemblyPath, ILogger logger, CommonOptions options, out string trapFile, out bool extracted)
{
trapFile = "";
extracted = false;
try
{
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache);
var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer, options);
var transformedAssemblyPath = pathTransformer.Transform(assemblyPath);
using var trapWriter = transformedAssemblyPath.WithSuffix(".cil").CreateTrapWriter(logger, options.TrapCompression, discardDuplicates: true);
trapFile = trapWriter.TrapFile;
if (!options.Cache || !System.IO.File.Exists(trapFile))
{
ExtractCIL(extractor, trapWriter, options.PDB);
extracted = true;
}
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
logger.LogError(string.Format("Exception extracting {0}: {1}", assemblyPath, ex));
}
}
}
}

View File

@@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A factory and a cache for mapping source entities to target entities.
/// Could be considered as a memoizer.
/// </summary>
/// <typeparam name="TSrc">The type of the source.</typeparam>
/// <typeparam name="TTarget">The type of the generated object.</typeparam>
public class CachedFunction<TSrc, TTarget> where TSrc : notnull
{
private readonly Func<TSrc, TTarget> generator;
private readonly Dictionary<TSrc, TTarget> cache;
/// <summary>
/// Initializes the factory with a given mapping.
/// </summary>
/// <param name="g">The mapping.</param>
public CachedFunction(Func<TSrc, TTarget> g)
{
generator = g;
cache = new Dictionary<TSrc, TTarget>();
}
/// <summary>
/// Gets the target for a given source.
/// Create it if it does not exist.
/// </summary>
/// <param name="src">The source object.</param>
/// <returns>The created object.</returns>
public TTarget this[TSrc src]
{
get
{
if (!cache.TryGetValue(src, out var result))
{
result = generator(src);
cache[src] = result;
}
return result;
}
}
}
/// <summary>
/// A factory for mapping a pair of source entities to a target entity.
/// </summary>
/// <typeparam name="TSrcEntity1">Source entity type 1.</typeparam>
/// <typeparam name="TSrcEntity2">Source entity type 2.</typeparam>
/// <typeparam name="TTarget">The target type.</typeparam>
public class CachedFunction<TSrcEntity1, TSrcEntity2, TTarget>
{
private readonly CachedFunction<(TSrcEntity1, TSrcEntity2), TTarget> factory;
/// <summary>
/// Initializes the factory with a given mapping.
/// </summary>
/// <param name="g">The mapping.</param>
public CachedFunction(Func<TSrcEntity1, TSrcEntity2, TTarget> g)
{
factory = new CachedFunction<(TSrcEntity1, TSrcEntity2), TTarget>(p => g(p.Item1, p.Item2));
}
public TTarget this[TSrcEntity1 s1, TSrcEntity2 s2] => factory[(s1, s2)];
}
}

View File

@@ -1,253 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// Provides methods for creating and caching various entities.
/// </summary>
internal sealed partial class Context
{
private readonly Dictionary<object, Label> ids = new Dictionary<object, Label>();
internal T Populate<T>(T e) where T : IExtractedEntity
{
if (e.Label.Valid)
{
return e; // Already populated
}
if (ids.TryGetValue(e, out var existing))
{
// It exists already
e.Label = existing;
}
else
{
e.Label = GetNewLabel();
DefineLabel(e);
ids.Add(e, e.Label);
PopulateLater(() =>
{
foreach (var c in e.Contents)
c.Extract(this);
});
#if DEBUG_LABELS
using var writer = new EscapingTextWriter();
e.WriteId(writer);
var id = writer.ToString();
if (debugLabels.TryGetValue(id, out var previousEntity))
{
Extractor.Message(new Message("Duplicate trap ID", id, null, severity: Util.Logging.Severity.Warning));
}
else
{
debugLabels.Add(id, e);
}
#endif
}
return e;
}
#if DEBUG_LABELS
private readonly Dictionary<string, IExtractedEntity> debugLabels = new Dictionary<string, IExtractedEntity>();
#endif
public IExtractedEntity Create(Handle h)
{
var entity = CreateGeneric(defaultGenericContext, h);
return entity;
}
// Lazily cache primitive types.
private readonly PrimitiveType[] primitiveTypes = new PrimitiveType[(int)PrimitiveTypeCode.Object + 1];
public PrimitiveType Create(PrimitiveTypeCode code)
{
var e = primitiveTypes[(int)code];
if (e is null)
{
e = new PrimitiveType(this, code)
{
Label = GetNewLabel()
};
DefineLabel(e);
primitiveTypes[(int)code] = e;
}
return e;
}
/// <summary>
/// Creates an entity from a Handle in a GenericContext.
/// The type of the returned entity depends on the type of the handle.
/// The GenericContext is needed because some handles are generics which
/// need to be expanded in terms of the current instantiation. If this sounds
/// complex, you are right.
///
/// The pair (h,genericContext) is cached in case it is needed again.
/// </summary>
/// <param name="h">The handle of the entity.</param>
/// <param name="genericContext">The generic context.</param>
/// <returns></returns>
public IExtractedEntity CreateGeneric(IGenericContext genericContext, Handle h) => genericHandleFactory[genericContext, h];
private readonly IGenericContext defaultGenericContext;
private IExtractedEntity CreateGenericHandle(IGenericContext gc, Handle handle)
{
IExtractedEntity entity;
switch (handle.Kind)
{
case HandleKind.MethodDefinition:
entity = new DefinitionMethod(gc, (MethodDefinitionHandle)handle);
break;
case HandleKind.MemberReference:
entity = Create(gc, (MemberReferenceHandle)handle);
break;
case HandleKind.MethodSpecification:
entity = new MethodSpecificationMethod(gc, (MethodSpecificationHandle)handle);
break;
case HandleKind.FieldDefinition:
entity = new DefinitionField(gc.Context, (FieldDefinitionHandle)handle);
break;
case HandleKind.TypeReference:
var tr = new TypeReferenceType(this, (TypeReferenceHandle)handle);
if (tr.TryGetPrimitiveType(out var pt))
// Map special names like `System.Int32` to `int`
return pt;
entity = tr;
break;
case HandleKind.TypeSpecification:
return Entities.Type.DecodeType(gc, (TypeSpecificationHandle)handle);
case HandleKind.TypeDefinition:
entity = new TypeDefinitionType(this, (TypeDefinitionHandle)handle);
break;
case HandleKind.StandaloneSignature:
var signature = MdReader.GetStandaloneSignature((StandaloneSignatureHandle)handle);
var method = signature.DecodeMethodSignature(gc.Context.TypeSignatureDecoder, gc);
entity = new FunctionPointerType(this, method);
break;
default:
throw new InternalError("Unhandled handle kind " + handle.Kind);
}
Populate(entity);
return entity;
}
private IExtractedEntity Create(IGenericContext gc, MemberReferenceHandle handle)
{
var mr = MdReader.GetMemberReference(handle);
switch (mr.GetKind())
{
case MemberReferenceKind.Method:
return new MemberReferenceMethod(gc, handle);
case MemberReferenceKind.Field:
return new MemberReferenceField(gc, handle);
default:
throw new InternalError("Unhandled member reference handle");
}
}
/// <summary>
/// Gets the string for a string handle.
/// </summary>
/// <param name="h">The string handle.</param>
/// <returns>The string.</returns>
public string GetString(StringHandle h) => MdReader.GetString(h);
#region Namespaces
private readonly CachedFunction<StringHandle, Namespace> namespaceFactory;
public Namespace CreateNamespace(StringHandle fqn) => namespaceFactory[fqn];
private readonly Lazy<Namespace> globalNamespace, systemNamespace;
/// <summary>
/// The entity representing the global namespace.
/// </summary>
public Namespace GlobalNamespace => globalNamespace.Value;
/// <summary>
/// The entity representing the System namespace.
/// </summary>
public Namespace SystemNamespace => systemNamespace.Value;
/// <summary>
/// Creates a namespace from a fully-qualified name.
/// </summary>
/// <param name="fqn">The fully-qualified namespace name.</param>
/// <returns>The namespace entity.</returns>
private Namespace CreateNamespace(string fqn) => Populate(new Namespace(this, fqn));
private readonly CachedFunction<NamespaceDefinitionHandle, Namespace> namespaceDefinitionFactory;
/// <summary>
/// Creates a namespace from a namespace handle.
/// </summary>
/// <param name="handle">The handle of the namespace.</param>
/// <returns>The namespace entity.</returns>
public Namespace Create(NamespaceDefinitionHandle handle) => namespaceDefinitionFactory[handle];
private Namespace CreateNamespace(NamespaceDefinitionHandle handle)
{
if (handle.IsNil)
return GlobalNamespace;
var nd = MdReader.GetNamespaceDefinition(handle);
return Populate(new Namespace(this, GetString(nd.Name), Create(nd.Parent)));
}
#endregion
#region Locations
private readonly CachedFunction<PDB.ISourceFile, PdbSourceFile> sourceFiles;
private readonly CachedFunction<PathTransformer.ITransformedPath, Folder> folders;
private readonly CachedFunction<PDB.Location, PdbSourceLocation> sourceLocations;
/// <summary>
/// Creates a source file entity from a PDB source file.
/// </summary>
/// <param name="file">The PDB source file.</param>
/// <returns>A source file entity.</returns>
public PdbSourceFile CreateSourceFile(PDB.ISourceFile file) => sourceFiles[file];
/// <summary>
/// Creates a folder entity with the given path.
/// </summary>
/// <param name="path">The path of the folder.</param>
/// <returns>A folder entity.</returns>
public Folder CreateFolder(PathTransformer.ITransformedPath path) => folders[path];
/// <summary>
/// Creates a source location.
/// </summary>
/// <param name="loc">The source location from PDB.</param>
/// <returns>A source location entity.</returns>
public PdbSourceLocation CreateSourceLocation(PDB.Location loc) => sourceLocations[loc];
#endregion
private readonly CachedFunction<IGenericContext, Handle, IExtractedEntity> genericHandleFactory;
/// <summary>
/// Gets the short name of a member, without the preceding interface qualifier.
/// </summary>
/// <param name="handle">The handle of the name.</param>
/// <returns>The short name.</returns>
public string ShortName(StringHandle handle)
{
var str = MdReader.GetString(handle);
if (str.EndsWith(".ctor"))
return ".ctor";
if (str.EndsWith(".cctor"))
return ".cctor";
var dot = str.LastIndexOf('.');
return dot == -1 ? str : str.Substring(dot + 1);
}
}
}

View File

@@ -1,115 +0,0 @@
using System;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// Extraction context for CIL extraction.
/// Adds additional context that is specific for CIL extraction.
/// One context = one DLL/EXE.
/// </summary>
internal sealed partial class Context : Extraction.Context, IDisposable
{
private readonly FileStream stream;
private Entities.Assembly? assemblyNull;
public MetadataReader MdReader { get; }
public PEReader PeReader { get; }
public string AssemblyPath { get; }
public Entities.Assembly Assembly
{
get { return assemblyNull!; }
set { assemblyNull = value; }
}
public PDB.IPdb? Pdb { get; }
public Context(Extractor extractor, TrapWriter trapWriter, string assemblyPath, bool extractPdbs)
: base(extractor, trapWriter)
{
this.AssemblyPath = assemblyPath;
stream = File.OpenRead(assemblyPath);
PeReader = new PEReader(stream, PEStreamOptions.PrefetchEntireImage);
MdReader = PeReader.GetMetadataReader();
TypeSignatureDecoder = new Entities.TypeSignatureDecoder(this);
globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "", null)));
systemNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "System")));
genericHandleFactory = new CachedFunction<IGenericContext, Handle, IExtractedEntity>(CreateGenericHandle);
namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(MdReader.GetString(n)));
namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace);
sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path));
folders = new CachedFunction<PathTransformer.ITransformedPath, Entities.Folder>(path => new Entities.Folder(this, path));
sourceLocations = new CachedFunction<PDB.Location, Entities.PdbSourceLocation>(location => new Entities.PdbSourceLocation(this, location));
defaultGenericContext = new EmptyContext(this);
if (extractPdbs)
{
Pdb = PDB.PdbReader.Create(assemblyPath, PeReader);
if (Pdb is not null)
{
Extractor.Logger.Log(Util.Logging.Severity.Info, string.Format("Found PDB information for {0}", assemblyPath));
}
}
}
public void Dispose()
{
if (Pdb is not null)
Pdb.Dispose();
PeReader.Dispose();
stream.Dispose();
}
/// <summary>
/// Extract the contents of a given entity.
/// </summary>
/// <param name="entity">The entity to extract.</param>
public void Extract(IExtractedEntity entity)
{
foreach (var content in entity.Contents)
{
content.Extract(this);
}
}
public void WriteAssemblyPrefix(TextWriter trapFile)
{
var def = MdReader.GetAssemblyDefinition();
trapFile.Write(GetString(def.Name));
trapFile.Write('_');
trapFile.Write(def.Version.ToString());
trapFile.Write(Entities.Type.AssemblyTypeNameSeparator);
}
public Entities.TypeSignatureDecoder TypeSignatureDecoder { get; }
/// <summary>
/// A type used to signify something we can't handle yet.
/// Specifically, function pointers (used in C++).
/// </summary>
public Entities.Type ErrorType
{
get
{
var errorType = new Entities.ErrorType(this);
Populate(errorType);
return errorType;
}
}
/// <summary>
/// Attempt to locate debugging information for a particular method.
///
/// Returns null on failure, for example if there was no PDB information found for the
/// DLL, or if the particular method is compiler generated or doesn't come from source code.
/// </summary>
/// <param name="handle">The handle of the method.</param>
/// <returns>The debugging information, or null if the information could not be located.</returns>
public PDB.Method? GetMethodDebugInformation(MethodDefinitionHandle handle)
{
return Pdb?.GetMethod(handle.ToDebugInformationHandle());
}
}
}

View File

@@ -1,22 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A generic context which does not contain any type parameters.
/// </summary>
internal class EmptyContext : IGenericContext
{
public EmptyContext(Context cx)
{
Context = cx;
}
public Context Context { get; }
public IEnumerable<Entities.Type> TypeParameters { get { yield break; } }
public IEnumerable<Entities.Type> MethodParameters { get { yield break; } }
}
}

View File

@@ -1,74 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An array type.
/// </summary>
internal sealed class ArrayType : Type
{
private readonly Type elementType;
private readonly int rank;
public ArrayType(Context cx, Type elementType, int rank) : base(cx)
{
this.rank = rank;
this.elementType = elementType;
}
public ArrayType(Context cx, Type elementType) : this(cx, elementType, 1)
{
}
public override bool Equals(object? obj)
{
return obj is ArrayType array && elementType.Equals(array.elementType) && rank == array.rank;
}
public override int GetHashCode() => HashCode.Combine(elementType, rank);
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
elementType.WriteId(trapFile, inContext);
trapFile.Write('[');
for (var i = 1; i < rank; ++i)
{
trapFile.Write(',');
}
trapFile.Write(']');
}
public override string Name => elementType.Name + "[]";
public override Namespace ContainingNamespace => Context.SystemNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => elementType.ThisTypeParameterCount;
public override CilTypeKind Kind => CilTypeKind.Array;
public override Type Construct(IEnumerable<Type> typeArguments) => Context.Populate(new ArrayType(Context, elementType.Construct(typeArguments)));
public override Type SourceDeclaration => Context.Populate(new ArrayType(Context, elementType.SourceDeclaration));
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
yield return c;
yield return Tuples.cil_array_type(this, elementType, rank);
}
}
public override void WriteAssemblyPrefix(TextWriter trapFile) => elementType.WriteAssemblyPrefix(trapFile);
public override IEnumerable<Type> GenericArguments => elementType.GenericArguments;
public override IEnumerable<Type> TypeParameters => elementType.TypeParameters;
}
}

View File

@@ -1,101 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An assembly to extract.
/// </summary>
internal class Assembly : LabelledEntity, ILocation
{
private readonly File file;
private readonly AssemblyName assemblyName;
public Assembly(Context cx) : base(cx)
{
cx.Assembly = this;
var def = cx.MdReader.GetAssemblyDefinition();
assemblyName = new AssemblyName
{
Name = cx.MdReader.GetString(def.Name),
Version = def.Version,
CultureInfo = new CultureInfo(cx.MdReader.GetString(def.Culture))
};
if (!def.PublicKey.IsNil)
assemblyName.SetPublicKey(cx.MdReader.GetBlobBytes(def.PublicKey));
file = new File(cx, cx.AssemblyPath);
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(FullName);
trapFile.Write("#file:///");
trapFile.Write(Context.AssemblyPath.Replace("\\", "/"));
trapFile.Write(";assembly");
}
public override bool Equals(object? obj)
{
return GetType() == obj?.GetType() && Equals(file, ((Assembly)obj).file);
}
public override int GetHashCode() => 7 * file.GetHashCode();
private string FullName => assemblyName.GetPublicKey() is null ? assemblyName.FullName + ", PublicKeyToken=null" : assemblyName.FullName;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return file;
yield return Tuples.assemblies(this, file, FullName, assemblyName.Name ?? string.Empty, assemblyName.Version?.ToString() ?? string.Empty);
if (Context.Pdb is not null)
{
foreach (var f in Context.Pdb.SourceFiles)
{
yield return Context.CreateSourceFile(f);
}
}
foreach (var handle in Context.MdReader.TypeDefinitions)
{
IExtractionProduct? product = null;
try
{
product = Context.Create(handle);
}
catch (InternalError e)
{
Context.ExtractionError("Error processing type definition", e.Message, GeneratedLocation.Create(Context), e.StackTrace);
}
// Limitation of C#: Cannot yield return inside a try-catch.
if (product is not null)
yield return product;
}
foreach (var handle in Context.MdReader.MethodDefinitions)
{
IExtractionProduct? product = null;
try
{
product = Context.Create(handle);
}
catch (InternalError e)
{
Context.ExtractionError("Error processing bytecode", e.Message, GeneratedLocation.Create(Context), e.StackTrace);
}
if (product is not null)
yield return product;
}
}
}
}
}

View File

@@ -1,90 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Entity representing a CIL attribute.
/// </summary>
internal sealed class Attribute : UnlabelledEntity
{
private readonly CustomAttributeHandle handle;
private readonly CustomAttribute attrib;
private readonly IExtractedEntity @object;
public Attribute(Context cx, IExtractedEntity @object, CustomAttributeHandle handle) : base(cx)
{
attrib = cx.MdReader.GetCustomAttribute(handle);
this.handle = handle;
this.@object = @object;
}
public override bool Equals(object? obj)
{
return obj is Attribute attribute && handle.Equals(attribute.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var constructor = (Method)Context.Create(attrib.Constructor);
yield return constructor;
yield return Tuples.cil_attribute(this, @object, constructor);
CustomAttributeValue<Type> decoded;
try
{
decoded = attrib.DecodeValue(new CustomAttributeDecoder(Context));
}
catch
{
Context.Extractor.Logger.Log(Util.Logging.Severity.Info,
$"Attribute decoding is partial. Decoding attribute {constructor.DeclaringType.GetQualifiedName()} failed on {@object}.");
yield break;
}
for (var index = 0; index < decoded.FixedArguments.Length; ++index)
{
var stringValue = GetStringValue(decoded.FixedArguments[index].Type, decoded.FixedArguments[index].Value);
yield return Tuples.cil_attribute_positional_argument(this, index, stringValue);
}
foreach (var p in decoded.NamedArguments)
{
var stringValue = GetStringValue(p.Type, p.Value);
yield return Tuples.cil_attribute_named_argument(this, p.Name!, stringValue);
}
}
}
private static string GetStringValue(Type type, object? value)
{
if (value is System.Collections.Immutable.ImmutableArray<CustomAttributeTypedArgument<Type>> values)
{
return "[" + string.Join(",", values.Select(v => GetStringValue(v.Type, v.Value))) + "]";
}
if (type.GetQualifiedName() == "System.Type" &&
value is Type t)
{
return t.GetQualifiedName();
}
return value?.ToString() ?? "null";
}
public static IEnumerable<IExtractionProduct> Populate(Context cx, IExtractedEntity @object, CustomAttributeHandleCollection attributes)
{
foreach (var attrib in attributes)
{
yield return new Attribute(cx, @object, attrib);
}
}
}
}

View File

@@ -1,16 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A CIL entity which has been extracted.
/// </summary>
internal interface IExtractedEntity : IExtractionProduct, IEntity
{
/// <summary>
/// The contents of the entity.
/// </summary>
IEnumerable<IExtractionProduct> Contents { get; }
}
}

View File

@@ -1,24 +0,0 @@
namespace Semmle.Extraction.CIL
{
/// <summary>
/// Something that is extracted from an entity.
/// </summary>
///
/// <remarks>
/// The extraction algorithm proceeds as follows:
/// - Construct entity
/// - Call Extract()
/// - IExtractedEntity check if already extracted
/// - Enumerate Contents to produce more extraction products
/// - Extract these until there is nothing left to extract
/// </remarks>
internal interface IExtractionProduct
{
/// <summary>
/// Perform further extraction/population of this item as necessary.
/// </summary>
///
/// <param name="cx">The extraction context.</param>
void Extract(Context cx);
}
}

View File

@@ -1,24 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// When we decode a type/method signature, we need access to
/// generic parameters.
/// </summary>
internal interface IGenericContext
{
Context Context { get; }
/// <summary>
/// The list of generic type parameters/arguments, including type parameters/arguments of
/// containing types.
/// </summary>
IEnumerable<Entities.Type> TypeParameters { get; }
/// <summary>
/// The list of generic method parameters/arguments.
/// </summary>
IEnumerable<Entities.Type> MethodParameters { get; }
}
}

View File

@@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// An entity that needs to be populated during extraction.
/// This assigns a key and optionally extracts its contents.
/// </summary>
internal abstract class LabelledEntity : Extraction.LabelledEntity, IExtractedEntity
{
public override Context Context => (Context)base.Context;
protected LabelledEntity(Context cx) : base(cx)
{
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public void Extract(Context cx2)
{
cx2.Populate(this);
}
public override string ToString()
{
using var writer = new EscapingTextWriter();
WriteQuotedId(writer);
return writer.ToString();
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
public abstract IEnumerable<IExtractionProduct> Contents { get; }
}
}

View File

@@ -1,22 +0,0 @@
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A tuple that is an extraction product.
/// </summary>
internal class Tuple : IExtractionProduct
{
private readonly Extraction.Tuple tuple;
public Tuple(string name, params object[] args)
{
tuple = new Extraction.Tuple(name, args);
}
public void Extract(Context cx)
{
cx.TrapWriter.Emit(tuple);
}
public override string ToString() => tuple.ToString();
}
}

View File

@@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// An entity that has contents to extract. There is no need to populate
/// a key as it's done in the constructor.
/// </summary>
internal abstract class UnlabelledEntity : Extraction.UnlabelledEntity, IExtractedEntity
{
public override Context Context => (Context)base.Context;
protected UnlabelledEntity(Context cx) : base(cx)
{
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public void Extract(Context cx2)
{
cx2.Extract(this);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
public abstract IEnumerable<IExtractionProduct> Contents { get; }
}
}

View File

@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Types that are passed by reference are not written directly to trap files. Instead, the annotation is stored on
/// the entity.
/// </summary>
internal sealed class ByRefType : Type
{
public ByRefType(Context cx, Type elementType) : base(cx)
{
ElementType = elementType;
}
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{ElementType.Name}&";
public Type ElementType { get; }
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
ElementType.WriteId(trapFile, inContext);
trapFile.Write('&');
}
}
}

View File

@@ -1,14 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// The CIL database type-kind.
/// </summary>
public enum CilTypeKind
{
ValueOrRefType,
TypeParameter,
Array,
Pointer,
FunctionPointer
}
}

View File

@@ -1,118 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A constructed type.
/// </summary>
internal sealed class ConstructedType : Type
{
private readonly Type unboundGenericType;
// Either null or notEmpty
private readonly Type[]? thisTypeArguments;
private readonly Type? containingType;
private readonly NamedTypeIdWriter idWriter;
public ConstructedType(Context cx, Type unboundType, IEnumerable<Type> typeArguments) : base(cx)
{
idWriter = new NamedTypeIdWriter(this);
var suppliedArgs = typeArguments.Count();
if (suppliedArgs != unboundType.TotalTypeParametersCount)
throw new InternalError("Unexpected number of type arguments in ConstructedType");
unboundGenericType = unboundType;
var thisParams = unboundType.ThisTypeParameterCount;
if (typeArguments.Count() == thisParams)
{
containingType = unboundType.ContainingType;
thisTypeArguments = typeArguments.ToArray();
}
else if (thisParams == 0)
{
// all type arguments belong to containing type
containingType = unboundType.ContainingType!.Construct(typeArguments);
}
else
{
// some type arguments belong to containing type
var parentParams = suppliedArgs - thisParams;
containingType = unboundType.ContainingType!.Construct(typeArguments.Take(parentParams));
thisTypeArguments = typeArguments.Skip(parentParams).ToArray();
}
}
public override bool Equals(object? obj)
{
if (obj is ConstructedType t && Equals(unboundGenericType, t.unboundGenericType) && Equals(containingType, t.containingType))
{
if (thisTypeArguments is null)
return t.thisTypeArguments is null;
if (!(t.thisTypeArguments is null))
return thisTypeArguments.SequenceEqual(t.thisTypeArguments);
}
return false;
}
public override int GetHashCode()
{
var h = unboundGenericType.GetHashCode();
h = 13 * h + (containingType is null ? 0 : containingType.GetHashCode());
if (!(thisTypeArguments is null))
h = h * 13 + thisTypeArguments.SequenceHash();
return h;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
yield return c;
var i = 0;
foreach (var type in ThisTypeArguments)
{
yield return type;
yield return Tuples.cil_type_argument(this, i++, type);
}
}
}
public override Type SourceDeclaration => unboundGenericType;
public override Type? ContainingType => containingType;
public override string Name => unboundGenericType.Name;
public override Namespace ContainingNamespace => unboundGenericType.ContainingNamespace!;
public override CilTypeKind Kind => unboundGenericType.Kind;
public override Type Construct(IEnumerable<Type> typeArguments)
{
throw new NotImplementedException();
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}
public override void WriteAssemblyPrefix(TextWriter trapFile) => unboundGenericType.WriteAssemblyPrefix(trapFile);
public override int ThisTypeParameterCount => thisTypeArguments?.Length ?? 0;
public override IEnumerable<Type> TypeParameters => GenericArguments;
public override IEnumerable<Type> ThisTypeArguments => thisTypeArguments.EnumerateNull();
public override IEnumerable<Type> ThisGenericArguments => thisTypeArguments.EnumerateNull();
}
}

View File

@@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Helper class to decode the attribute structure.
/// Note that there are some unhandled cases that should be fixed in due course.
/// </summary>
internal class CustomAttributeDecoder : ICustomAttributeTypeProvider<Type>
{
private readonly Context cx;
public CustomAttributeDecoder(Context cx) { this.cx = cx; }
public Type GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Create(typeCode);
public Type GetSystemType() => new NoMetadataHandleType(cx, "System.Type");
public Type GetSZArrayType(Type elementType) =>
cx.Populate(new ArrayType(cx, elementType));
public Type GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
public Type GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
public Type GetTypeFromSerializedName(string name) => new NoMetadataHandleType(cx, name);
public PrimitiveTypeCode GetUnderlyingEnumType(Type type)
{
if (type is TypeDefinitionType tdt &&
tdt.GetUnderlyingEnumType() is PrimitiveTypeCode underlying)
{
return underlying;
}
var name = type.GetQualifiedName();
if (wellKnownEnums.TryGetValue(name, out var code))
{
cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Using hard coded underlying enum type for {name}");
return code;
}
cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Couldn't get underlying enum type for {name}");
// We can't fall back to Int32, because the type returned here defines how many bytes are read from the
// stream and how those bytes are interpreted.
throw new NotImplementedException();
}
public bool IsSystemType(Type type) => type.GetQualifiedName() == "System.Type";
private static readonly Dictionary<string, PrimitiveTypeCode> wellKnownEnums = new Dictionary<string, PrimitiveTypeCode>
{
{ "System.AttributeTargets", PrimitiveTypeCode.Int32 },
{ "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 },
{ "System.Diagnostics.DebuggerBrowsableState", PrimitiveTypeCode.Int32 }
};
}
}

View File

@@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class DefinitionField : Field
{
private readonly Handle handle;
private readonly FieldDefinition fd;
public DefinitionField(Context cx, FieldDefinitionHandle handle) : base(cx)
{
this.handle = handle;
fd = Context.MdReader.GetFieldDefinition(handle);
}
public override bool Equals(object? obj)
{
return obj is DefinitionField field && handle.Equals(field.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.metadata_handle(this, Context.Assembly, MetadataTokens.GetToken(handle));
foreach (var c in base.Contents)
yield return c;
if (fd.Attributes.HasFlag(FieldAttributes.Private))
yield return Tuples.cil_private(this);
if (fd.Attributes.HasFlag(FieldAttributes.Public))
yield return Tuples.cil_public(this);
if (fd.Attributes.HasFlag(FieldAttributes.Family))
yield return Tuples.cil_protected(this);
if (fd.Attributes.HasFlag(FieldAttributes.Static))
yield return Tuples.cil_static(this);
if (fd.Attributes.HasFlag(FieldAttributes.Assembly))
yield return Tuples.cil_internal(this);
foreach (var c in Attribute.Populate(Context, this, fd.GetCustomAttributes()))
yield return c;
}
}
public override string Name => Context.GetString(fd.Name);
public override Type DeclaringType => (Type)Context.Create(fd.GetDeclaringType());
public override Type Type => fd.DecodeSignature(Context.TypeSignatureDecoder, DeclaringType);
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override IEnumerable<Type> MethodParameters => throw new NotImplementedException();
}
}

View File

@@ -1,299 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A definition method - a method defined in the current assembly.
/// </summary>
internal sealed class DefinitionMethod : Method
{
private readonly Handle handle;
private readonly MethodDefinition md;
private readonly PDB.Method? methodDebugInformation;
private readonly Type declaringType;
private readonly string name;
private LocalVariable[]? locals;
public MethodImplementation? Implementation { get; private set; }
public override IList<LocalVariable>? LocalVariables => locals;
public DefinitionMethod(IGenericContext gc, MethodDefinitionHandle handle) : base(gc)
{
md = Context.MdReader.GetMethodDefinition(handle);
this.gc = gc;
this.handle = handle;
name = Context.GetString(md.Name);
declaringType = (Type)Context.CreateGeneric(this, md.GetDeclaringType());
signature = md.DecodeSignature(new SignatureDecoder(), this);
methodDebugInformation = Context.GetMethodDebugInformation(handle);
}
public override bool Equals(object? obj)
{
return obj is DefinitionMethod method && handle.Equals(method.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override bool IsStatic => !signature.Header.IsInstance;
public override Type DeclaringType => declaringType;
public override string Name => Context.ShortName(md.Name);
public override string NameLabel => name;
/// <summary>
/// Holds if this method has bytecode.
/// </summary>
public bool HasBytecode => md.ImplAttributes == MethodImplAttributes.IL && md.RelativeVirtualAddress != 0;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (md.GetGenericParameters().Any())
{
// We need to perform a 2-phase population because some type parameters can
// depend on other type parameters (as a constraint).
genericParams = new MethodTypeParameter[md.GetGenericParameters().Count];
for (var i = 0; i < genericParams.Length; ++i)
genericParams[i] = Context.Populate(new MethodTypeParameter(this, this, i));
for (var i = 0; i < genericParams.Length; ++i)
genericParams[i].PopulateHandle(md.GetGenericParameters()[i]);
foreach (var p in genericParams)
yield return p;
}
var typeSignature = md.DecodeSignature(Context.TypeSignatureDecoder, this);
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var c in parameters)
yield return c;
foreach (var c in PopulateFlags)
yield return c;
foreach (var p in md.GetParameters().Select(h => Context.MdReader.GetParameter(h)).Where(p => p.SequenceNumber > 0))
{
var pe = Parameters[IsStatic ? p.SequenceNumber - 1 : p.SequenceNumber];
if (p.Attributes.HasFlag(ParameterAttributes.Out))
yield return Tuples.cil_parameter_out(pe);
if (p.Attributes.HasFlag(ParameterAttributes.In))
yield return Tuples.cil_parameter_in(pe);
foreach (var c in Attribute.Populate(Context, pe, p.GetCustomAttributes()))
yield return c;
}
yield return Tuples.metadata_handle(this, Context.Assembly, MetadataTokens.GetToken(handle));
foreach (var m in GetMethodExtractionProducts(Name, declaringType, typeSignature.ReturnType))
{
yield return m;
}
yield return Tuples.cil_method_source_declaration(this, this);
yield return Tuples.cil_method_location(this, Context.Assembly);
if (HasBytecode)
{
Implementation = new MethodImplementation(this);
yield return Implementation;
var body = Context.PeReader.GetMethodBody(md.RelativeVirtualAddress);
if (!body.LocalSignature.IsNil)
{
var localVariableTypes = System.Collections.Immutable.ImmutableArray<Type>.Empty;
var hasError = false;
try
{
var locals = Context.MdReader.GetStandaloneSignature(body.LocalSignature);
localVariableTypes = locals.DecodeLocalSignature(Context.TypeSignatureDecoder, this);
}
catch (System.BadImageFormatException exc)
{
Context.Extractor.Logger.Log(Util.Logging.Severity.Info,
$"Could not decode locals in method {declaringType.GetQualifiedName()}.{name}. {exc}");
hasError = true;
}
if (!hasError)
{
this.locals = new LocalVariable[localVariableTypes.Length];
for (var l = 0; l < this.locals.Length; ++l)
{
var t = localVariableTypes[l];
if (t is ByRefType brt)
{
t = brt.ElementType;
this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t));
yield return this.locals[l];
yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref);
}
else
{
this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t));
yield return this.locals[l];
}
}
}
}
var jump_table = new Dictionary<int, Instruction>();
foreach (var c in Decode(body.GetILBytes(), jump_table))
yield return c;
var filter_index = 0;
foreach (var region in body.ExceptionRegions)
{
yield return new ExceptionRegion(this, Implementation, filter_index++, region, jump_table);
}
yield return Tuples.cil_method_stack_size(Implementation, body.MaxStack);
if (methodDebugInformation is not null)
{
var sourceLocation = Context.CreateSourceLocation(methodDebugInformation.Location);
yield return sourceLocation;
yield return Tuples.cil_method_location(this, sourceLocation);
}
}
// Flags
if (md.Attributes.HasFlag(MethodAttributes.Private))
yield return Tuples.cil_private(this);
if (md.Attributes.HasFlag(MethodAttributes.Public))
yield return Tuples.cil_public(this);
if (md.Attributes.HasFlag(MethodAttributes.Family))
yield return Tuples.cil_protected(this);
if (md.Attributes.HasFlag(MethodAttributes.Final))
yield return Tuples.cil_sealed(this);
if (md.Attributes.HasFlag(MethodAttributes.Virtual))
yield return Tuples.cil_virtual(this);
if (md.Attributes.HasFlag(MethodAttributes.Abstract))
yield return Tuples.cil_abstract(this);
if (md.Attributes.HasFlag(MethodAttributes.HasSecurity))
yield return Tuples.cil_security(this);
if (md.Attributes.HasFlag(MethodAttributes.RequireSecObject))
yield return Tuples.cil_requiresecobject(this);
if (md.Attributes.HasFlag(MethodAttributes.SpecialName))
yield return Tuples.cil_specialname(this);
if (md.Attributes.HasFlag(MethodAttributes.NewSlot))
yield return Tuples.cil_newslot(this);
// Populate attributes
foreach (var c in Attribute.Populate(Context, this, md.GetCustomAttributes()))
yield return c;
}
}
private IEnumerable<IExtractionProduct> Decode(byte[]? ilbytes, Dictionary<int, Instruction> jump_table)
{
// Sequence points are stored in order of offset.
// We use an enumerator to locate the correct sequence point for each instruction.
// The sequence point gives the location of each instruction.
// The location of an instruction is given by the sequence point *after* the
// instruction.
IEnumerator<PDB.SequencePoint>? nextSequencePoint = null;
PdbSourceLocation? instructionLocation = null;
if (methodDebugInformation is not null)
{
nextSequencePoint = methodDebugInformation.SequencePoints.GetEnumerator();
if (nextSequencePoint.MoveNext())
{
instructionLocation = Context.CreateSourceLocation(nextSequencePoint.Current.Location);
yield return instructionLocation;
}
else
{
nextSequencePoint = null;
}
}
var child = 0;
for (var offset = 0; offset < (ilbytes?.Length ?? 0);)
{
var instruction = new Instruction(Context, this, ilbytes!, offset, child++);
yield return instruction;
if (nextSequencePoint is not null && offset >= nextSequencePoint.Current.Offset)
{
instructionLocation = Context.CreateSourceLocation(nextSequencePoint.Current.Location);
yield return instructionLocation;
if (!nextSequencePoint.MoveNext())
nextSequencePoint = null;
}
if (instructionLocation is not null)
yield return Tuples.cil_instruction_location(instruction, instructionLocation);
jump_table.Add(instruction.Offset, instruction);
offset += instruction.Width;
}
foreach (var i in jump_table)
{
foreach (var t in i.Value.JumpContents(jump_table))
yield return t;
}
}
/// <summary>
/// Display the instructions in the method in the debugger.
/// This is only used for debugging, not in the code itself.
/// </summary>
public IEnumerable<Instruction> DebugInstructions
{
get
{
if (md.ImplAttributes == MethodImplAttributes.IL && md.RelativeVirtualAddress != 0)
{
var body = Context.PeReader.GetMethodBody(md.RelativeVirtualAddress);
var ilbytes = body.GetILBytes();
var child = 0;
for (var offset = 0; offset < (ilbytes?.Length ?? 0);)
{
Instruction decoded;
try
{
decoded = new Instruction(Context, this, ilbytes!, offset, child++);
offset += decoded.Width;
}
catch // lgtm[cs/catch-of-all-exceptions]
{
yield break;
}
yield return decoded;
}
}
}
}
}
}

View File

@@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class ErrorType : Type
{
public ErrorType(Context cx) : base(cx)
{
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext) => trapFile.Write("<ErrorType>");
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override string Name => "!error";
public override Namespace ContainingNamespace => Context.GlobalNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => 0;
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
}
}

View File

@@ -1,73 +0,0 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An event entity.
/// </summary>
internal sealed class Event : LabelledEntity
{
private readonly EventDefinitionHandle handle;
private readonly Type parent;
private readonly EventDefinition ed;
public Event(Context cx, Type parent, EventDefinitionHandle handle) : base(cx)
{
this.handle = handle;
this.parent = parent;
ed = cx.MdReader.GetEventDefinition(handle);
}
public override void WriteId(EscapingTextWriter trapFile)
{
parent.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(Context.ShortName(ed.Name));
trapFile.Write(";cil-event");
}
public override bool Equals(object? obj)
{
return obj is Event e && handle.Equals(e.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var signature = (Type)Context.CreateGeneric(parent, ed.Type);
yield return signature;
yield return Tuples.cil_event(this, parent, Context.ShortName(ed.Name), signature);
var accessors = ed.GetAccessors();
if (!accessors.Adder.IsNil)
{
var adder = (Method)Context.CreateGeneric(parent, accessors.Adder);
yield return adder;
yield return Tuples.cil_adder(this, adder);
}
if (!accessors.Remover.IsNil)
{
var remover = (Method)Context.CreateGeneric(parent, accessors.Remover);
yield return remover;
yield return Tuples.cil_remover(this, remover);
}
if (!accessors.Raiser.IsNil)
{
var raiser = (Method)Context.CreateGeneric(parent, accessors.Raiser);
yield return raiser;
yield return Tuples.cil_raiser(this, raiser);
}
foreach (var c in Attribute.Populate(Context, this, ed.GetCustomAttributes()))
yield return c;
}
}
}
}

View File

@@ -1,56 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An exception region entity.
/// </summary>
internal class ExceptionRegion : UnlabelledEntity
{
private readonly IGenericContext gc;
private readonly MethodImplementation method;
private readonly int index;
private readonly System.Reflection.Metadata.ExceptionRegion r;
private readonly Dictionary<int, Instruction> jump_table;
public ExceptionRegion(IGenericContext gc, MethodImplementation method, int index, System.Reflection.Metadata.ExceptionRegion r, Dictionary<int, Instruction> jump_table) : base(gc.Context)
{
this.gc = gc;
this.method = method;
this.index = index;
this.r = r;
this.jump_table = jump_table;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (!jump_table.TryGetValue(r.TryOffset, out var try_start))
throw new InternalError("Failed to retrieve handler");
if (!jump_table.TryGetValue(r.TryOffset + r.TryLength, out var try_end))
throw new InternalError("Failed to retrieve handler");
if (!jump_table.TryGetValue(r.HandlerOffset, out var handler_start))
throw new InternalError("Failed to retrieve handler");
yield return Tuples.cil_handler(this, method, index, (int)r.Kind, try_start, try_end, handler_start);
if (r.FilterOffset != -1)
{
if (!jump_table.TryGetValue(r.FilterOffset, out var filter_start))
throw new InternalError("ExceptionRegion filter clause");
yield return Tuples.cil_handler_filter(this, filter_start);
}
if (!r.CatchType.IsNil)
{
var catchType = (Type)Context.CreateGeneric(gc, r.CatchType);
yield return catchType;
yield return Tuples.cil_handler_type(this, catchType);
}
}
}
}
}

View File

@@ -1,51 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An entity representing a field.
/// </summary>
internal abstract class Field : LabelledEntity, IGenericContext, IMember, ICustomModifierReceiver
{
protected Field(Context cx) : base(cx)
{
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(DeclaringType);
trapFile.Write('.');
trapFile.Write(Name);
trapFile.Write(";cil-field");
}
public abstract string Name { get; }
public abstract Type DeclaringType { get; }
public abstract Type Type { get; }
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var t = Type;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_field(this, DeclaringType, Name, t);
}
}
public abstract IEnumerable<Type> TypeParameters { get; }
public abstract IEnumerable<Type> MethodParameters { get; }
}
}

View File

@@ -1,43 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal class File : LabelledEntity, IFileOrFolder
{
protected string OriginalPath { get; }
protected PathTransformer.ITransformedPath TransformedPath { get; }
public File(Context cx, string path) : base(cx)
{
this.OriginalPath = path;
TransformedPath = Context.Extractor.PathTransformer.Transform(OriginalPath);
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(TransformedPath.DatabaseId);
trapFile.Write(";sourcefile");
}
public override bool Equals(object? obj)
{
return GetType() == obj?.GetType() && OriginalPath == ((File)obj).OriginalPath;
}
public override int GetHashCode() => 11 * OriginalPath.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (TransformedPath.ParentDirectory is PathTransformer.ITransformedPath dir)
{
var parent = Context.CreateFolder(dir);
yield return parent;
yield return Tuples.containerparent(parent, this);
}
yield return Tuples.files(this, TransformedPath.Value);
}
}
}
}

View File

@@ -1,41 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class Folder : LabelledEntity, IFileOrFolder
{
private readonly PathTransformer.ITransformedPath transformedPath;
public Folder(Context cx, PathTransformer.ITransformedPath path) : base(cx)
{
this.transformedPath = path;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(transformedPath.DatabaseId);
trapFile.Write(";folder");
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (transformedPath.ParentDirectory is PathTransformer.ITransformedPath parent)
{
var parentFolder = Context.CreateFolder(parent);
yield return parentFolder;
yield return Tuples.containerparent(parentFolder, this);
}
yield return Tuples.folders(this, transformedPath.Value);
}
}
public override bool Equals(object? obj)
{
return obj is Folder folder && transformedPath == folder.transformedPath;
}
public override int GetHashCode() => transformedPath.GetHashCode();
}
}

View File

@@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver
{
private readonly MethodSignature<Type> signature;
public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx)
{
this.signature = signature;
}
public override CilTypeKind Kind => CilTypeKind.FunctionPointer;
public override string Name
{
get
{
using var id = new StringWriter();
WriteName(
id.Write,
t => id.Write(t.Name),
signature
);
return id.ToString();
}
}
public override Namespace? ContainingNamespace => Context.GlobalNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => throw new System.NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException();
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
WriteName(
trapFile.Write,
t => t.WriteId(trapFile, inContext),
signature
);
}
internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature)
{
write("delegate* ");
write(GetCallingConvention(signature.Header.CallingConvention));
write("<");
foreach (var pt in signature.ParameterTypes)
{
writeType(pt);
write(",");
}
writeType(signature.ReturnType);
write(">");
}
internal static string GetCallingConvention(SignatureCallingConvention callingConvention)
{
if (callingConvention == SignatureCallingConvention.Default)
{
return "managed";
}
if (callingConvention == SignatureCallingConvention.Unmanaged)
{
return "unmanaged";
}
return $"unmanaged[{callingConvention}]";
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
{
yield return c;
}
var retType = signature.ReturnType;
if (retType is ModifiedType mt)
{
retType = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (retType is ByRefType byRefType)
{
retType = byRefType.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_function_pointer_return_type(this, retType);
yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention);
foreach (var p in Method.GetParameterExtractionProducts(signature.ParameterTypes, this, this, Context, 0))
{
yield return p;
}
}
}
}
}

View File

@@ -1,59 +0,0 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal static class GenericsHelper
{
public static TypeTypeParameter[] MakeTypeParameters(Type container, int count)
{
var newTypeParams = new TypeTypeParameter[count];
for (var i = 0; i < newTypeParams.Length; ++i)
{
newTypeParams[i] = new TypeTypeParameter(container, i);
}
return newTypeParams;
}
public static string GetNonGenericName(StringHandle name, MetadataReader reader)
{
var n = reader.GetString(name);
return GetNonGenericName(n);
}
public static string GetNonGenericName(string name)
{
var tick = name.LastIndexOf('`');
return tick == -1
? name
: name.Substring(0, tick);
}
public static int GetGenericTypeParameterCount(StringHandle name, MetadataReader reader)
{
var n = reader.GetString(name);
return GetGenericTypeParameterCount(n);
}
public static int GetGenericTypeParameterCount(string name)
{
var tick = name.LastIndexOf('`');
return tick == -1
? 0
: int.Parse(name.Substring(tick + 1));
}
public static IEnumerable<Type> GetAllTypeParameters(Type? container, IEnumerable<TypeTypeParameter> thisTypeParameters)
{
if (container is not null)
{
foreach (var t in container.TypeParameters)
yield return t;
}
foreach (var t in thisTypeParameters)
yield return t;
}
}
}

View File

@@ -1,6 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface IFileOrFolder : IEntity
{
}
}

View File

@@ -1,6 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
public interface ILocation : IEntity
{
}
}

View File

@@ -1,10 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An entity representing a member.
/// Used to type tuples correctly.
/// </summary>
internal interface IMember : IExtractedEntity
{
}
}

View File

@@ -1,7 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface IParameterizable : IEntity
{
}
}

View File

@@ -1,7 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface ITypeSignature
{
void WriteId(EscapingTextWriter trapFile, IGenericContext gc);
}
}

View File

@@ -1,508 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A CIL instruction.
/// </summary>
internal class Instruction : UnlabelledEntity
{
/// <summary>
/// The additional data following the opcode, if any.
/// </summary>
public enum Payload
{
None, TypeTok, Field, Target8, Class,
Method, Arg8, Local8, Target32, Int8,
Int16, Int32, Int64, Float32, Float64,
CallSiteDesc, Switch, String, Constructor, ValueType,
Type, Arg16, Ignore8, Token, Local16, MethodRef
}
/// <summary>
/// For each Payload, how many additional bytes in the bytestream need to be read.
/// </summary>
private static readonly int[] payloadSizes = {
0, 4, 4, 1, 4,
4, 1, 1, 4, 1,
2, 4, 8, 4, 8,
4, -1, 4, 4, 4,
4, 2, 1, 4, 2, 4 };
// Maps opcodes to payloads for each instruction.
private static readonly Dictionary<ILOpCode, Payload> opPayload = new Dictionary<ILOpCode, Payload>()
{
{ ILOpCode.Nop, Payload.None },
{ ILOpCode.Break, Payload.None },
{ ILOpCode.Ldarg_0, Payload.None },
{ ILOpCode.Ldarg_1, Payload.None },
{ ILOpCode.Ldarg_2, Payload.None },
{ ILOpCode.Ldarg_3, Payload.None },
{ ILOpCode.Ldloc_0, Payload.None },
{ ILOpCode.Ldloc_1, Payload.None },
{ ILOpCode.Ldloc_2, Payload.None },
{ ILOpCode.Ldloc_3, Payload.None },
{ ILOpCode.Stloc_0, Payload.None },
{ ILOpCode.Stloc_1, Payload.None },
{ ILOpCode.Stloc_2, Payload.None },
{ ILOpCode.Stloc_3, Payload.None },
{ ILOpCode.Ldarg_s, Payload.Arg8 },
{ ILOpCode.Ldarga_s, Payload.Arg8 },
{ ILOpCode.Starg_s, Payload.Arg8 },
{ ILOpCode.Ldloc_s, Payload.Local8 },
{ ILOpCode.Ldloca_s, Payload.Local8 },
{ ILOpCode.Stloc_s, Payload.Local8 },
{ ILOpCode.Ldnull, Payload.None },
{ ILOpCode.Ldc_i4_m1, Payload.None },
{ ILOpCode.Ldc_i4_0, Payload.None },
{ ILOpCode.Ldc_i4_1, Payload.None },
{ ILOpCode.Ldc_i4_2, Payload.None },
{ ILOpCode.Ldc_i4_3, Payload.None },
{ ILOpCode.Ldc_i4_4, Payload.None },
{ ILOpCode.Ldc_i4_5, Payload.None },
{ ILOpCode.Ldc_i4_6, Payload.None },
{ ILOpCode.Ldc_i4_7, Payload.None },
{ ILOpCode.Ldc_i4_8, Payload.None },
{ ILOpCode.Ldc_i4_s, Payload.Int8 },
{ ILOpCode.Ldc_i4, Payload.Int32 },
{ ILOpCode.Ldc_i8, Payload.Int64 },
{ ILOpCode.Ldc_r4, Payload.Float32 },
{ ILOpCode.Ldc_r8, Payload.Float64 },
{ ILOpCode.Dup, Payload.None },
{ ILOpCode.Pop, Payload.None },
{ ILOpCode.Jmp, Payload.Method },
{ ILOpCode.Call, Payload.Method },
{ ILOpCode.Calli, Payload.CallSiteDesc },
{ ILOpCode.Ret, Payload.None },
{ ILOpCode.Br_s, Payload.Target8 },
{ ILOpCode.Brfalse_s, Payload.Target8 },
{ ILOpCode.Brtrue_s, Payload.Target8 },
{ ILOpCode.Beq_s, Payload.Target8 },
{ ILOpCode.Bge_s, Payload.Target8 },
{ ILOpCode.Bgt_s, Payload.Target8 },
{ ILOpCode.Ble_s, Payload.Target8 },
{ ILOpCode.Blt_s, Payload.Target8 },
{ ILOpCode.Bne_un_s, Payload.Target8 },
{ ILOpCode.Bge_un_s, Payload.Target8 },
{ ILOpCode.Bgt_un_s, Payload.Target8 },
{ ILOpCode.Ble_un_s, Payload.Target8 },
{ ILOpCode.Blt_un_s, Payload.Target8 },
{ ILOpCode.Br, Payload.Target32 },
{ ILOpCode.Brfalse, Payload.Target32 },
{ ILOpCode.Brtrue, Payload.Target32 },
{ ILOpCode.Beq, Payload.Target32 },
{ ILOpCode.Bge, Payload.Target32 },
{ ILOpCode.Bgt, Payload.Target32 },
{ ILOpCode.Ble, Payload.Target32 },
{ ILOpCode.Blt, Payload.Target32 },
{ ILOpCode.Bne_un, Payload.Target32 },
{ ILOpCode.Bge_un, Payload.Target32 },
{ ILOpCode.Bgt_un, Payload.Target32 },
{ ILOpCode.Ble_un, Payload.Target32 },
{ ILOpCode.Blt_un, Payload.Target32 },
{ ILOpCode.Switch, Payload.Switch },
{ ILOpCode.Ldind_i1, Payload.None },
{ ILOpCode.Ldind_u1, Payload.None },
{ ILOpCode.Ldind_i2, Payload.None },
{ ILOpCode.Ldind_u2, Payload.None },
{ ILOpCode.Ldind_i4, Payload.None },
{ ILOpCode.Ldind_u4, Payload.None },
{ ILOpCode.Ldind_i8, Payload.None },
{ ILOpCode.Ldind_i, Payload.None },
{ ILOpCode.Ldind_r4, Payload.None },
{ ILOpCode.Ldind_r8, Payload.None },
{ ILOpCode.Ldind_ref, Payload.None },
{ ILOpCode.Stind_ref, Payload.None },
{ ILOpCode.Stind_i1, Payload.None },
{ ILOpCode.Stind_i2, Payload.None },
{ ILOpCode.Stind_i4, Payload.None },
{ ILOpCode.Stind_i8, Payload.None },
{ ILOpCode.Stind_r4, Payload.None },
{ ILOpCode.Stind_r8, Payload.None },
{ ILOpCode.Add, Payload.None },
{ ILOpCode.Sub, Payload.None },
{ ILOpCode.Mul, Payload.None },
{ ILOpCode.Div, Payload.None },
{ ILOpCode.Div_un, Payload.None },
{ ILOpCode.Rem, Payload.None },
{ ILOpCode.Rem_un, Payload.None },
{ ILOpCode.And, Payload.None },
{ ILOpCode.Or, Payload.None },
{ ILOpCode.Xor, Payload.None },
{ ILOpCode.Shl, Payload.None },
{ ILOpCode.Shr, Payload.None },
{ ILOpCode.Shr_un, Payload.None },
{ ILOpCode.Neg, Payload.None },
{ ILOpCode.Not, Payload.None },
{ ILOpCode.Conv_i1, Payload.None },
{ ILOpCode.Conv_i2, Payload.None },
{ ILOpCode.Conv_i4, Payload.None },
{ ILOpCode.Conv_i8, Payload.None },
{ ILOpCode.Conv_r4, Payload.None },
{ ILOpCode.Conv_r8, Payload.None },
{ ILOpCode.Conv_u4, Payload.None },
{ ILOpCode.Conv_u8, Payload.None },
{ ILOpCode.Callvirt, Payload.MethodRef },
{ ILOpCode.Cpobj, Payload.TypeTok },
{ ILOpCode.Ldobj, Payload.TypeTok },
{ ILOpCode.Ldstr, Payload.String },
{ ILOpCode.Newobj, Payload.Constructor },
{ ILOpCode.Castclass, Payload.Class },
{ ILOpCode.Isinst, Payload.Class },
{ ILOpCode.Conv_r_un, Payload.None },
{ ILOpCode.Unbox, Payload.ValueType },
{ ILOpCode.Throw, Payload.None },
{ ILOpCode.Ldfld, Payload.Field },
{ ILOpCode.Ldflda, Payload.Field },
{ ILOpCode.Stfld, Payload.Field },
{ ILOpCode.Ldsfld, Payload.Field },
{ ILOpCode.Ldsflda, Payload.Field },
{ ILOpCode.Stsfld, Payload.Field },
{ ILOpCode.Stobj, Payload.Field },
{ ILOpCode.Conv_ovf_i1_un, Payload.None },
{ ILOpCode.Conv_ovf_i2_un, Payload.None },
{ ILOpCode.Conv_ovf_i4_un, Payload.None },
{ ILOpCode.Conv_ovf_i8_un, Payload.None },
{ ILOpCode.Conv_ovf_u1_un, Payload.None },
{ ILOpCode.Conv_ovf_u2_un, Payload.None },
{ ILOpCode.Conv_ovf_u4_un, Payload.None },
{ ILOpCode.Conv_ovf_u8_un, Payload.None },
{ ILOpCode.Conv_ovf_i_un, Payload.None },
{ ILOpCode.Conv_ovf_u_un, Payload.None },
{ ILOpCode.Box, Payload.TypeTok },
{ ILOpCode.Newarr, Payload.TypeTok },
{ ILOpCode.Ldlen, Payload.None },
{ ILOpCode.Ldelema, Payload.Class },
{ ILOpCode.Ldelem_i1, Payload.None },
{ ILOpCode.Ldelem_u1, Payload.None },
{ ILOpCode.Ldelem_i2, Payload.None },
{ ILOpCode.Ldelem_u2, Payload.None },
{ ILOpCode.Ldelem_i4, Payload.None },
{ ILOpCode.Ldelem_u4, Payload.None },
{ ILOpCode.Ldelem_i8, Payload.None },
{ ILOpCode.Ldelem_i, Payload.None },
{ ILOpCode.Ldelem_r4, Payload.None },
{ ILOpCode.Ldelem_r8, Payload.None },
{ ILOpCode.Ldelem_ref, Payload.None },
{ ILOpCode.Stelem_i, Payload.None },
{ ILOpCode.Stelem_i1, Payload.None },
{ ILOpCode.Stelem_i2, Payload.None },
{ ILOpCode.Stelem_i4, Payload.None },
{ ILOpCode.Stelem_i8, Payload.None },
{ ILOpCode.Stelem_r4, Payload.None },
{ ILOpCode.Stelem_r8, Payload.None },
{ ILOpCode.Stelem_ref, Payload.None },
{ ILOpCode.Ldelem, Payload.TypeTok },
{ ILOpCode.Stelem, Payload.TypeTok },
{ ILOpCode.Unbox_any, Payload.TypeTok },
{ ILOpCode.Conv_ovf_i1, Payload.None },
{ ILOpCode.Conv_ovf_u1, Payload.None },
{ ILOpCode.Conv_ovf_i2, Payload.None },
{ ILOpCode.Conv_ovf_u2, Payload.None },
{ ILOpCode.Conv_ovf_i4, Payload.None },
{ ILOpCode.Conv_ovf_u4, Payload.None },
{ ILOpCode.Conv_ovf_i8, Payload.None },
{ ILOpCode.Conv_ovf_u8, Payload.None },
{ ILOpCode.Refanyval, Payload.Type },
{ ILOpCode.Ckfinite, Payload.None },
{ ILOpCode.Mkrefany, Payload.Class },
{ ILOpCode.Ldtoken, Payload.Token },
{ ILOpCode.Conv_u2, Payload.None },
{ ILOpCode.Conv_u1, Payload.None },
{ ILOpCode.Conv_i, Payload.None },
{ ILOpCode.Conv_ovf_i, Payload.None },
{ ILOpCode.Conv_ovf_u, Payload.None },
{ ILOpCode.Add_ovf, Payload.None },
{ ILOpCode.Add_ovf_un, Payload.None },
{ ILOpCode.Mul_ovf, Payload.None },
{ ILOpCode.Mul_ovf_un, Payload.None },
{ ILOpCode.Sub_ovf, Payload.None },
{ ILOpCode.Sub_ovf_un, Payload.None },
{ ILOpCode.Endfinally, Payload.None },
{ ILOpCode.Leave, Payload.Target32 },
{ ILOpCode.Leave_s, Payload.Target8 },
{ ILOpCode.Stind_i, Payload.None },
{ ILOpCode.Conv_u, Payload.None },
{ ILOpCode.Arglist, Payload.None },
{ ILOpCode.Ceq, Payload.None },
{ ILOpCode.Cgt, Payload.None },
{ ILOpCode.Cgt_un, Payload.None },
{ ILOpCode.Clt, Payload.None },
{ ILOpCode.Clt_un, Payload.None },
{ ILOpCode.Ldftn, Payload.Method },
{ ILOpCode.Ldvirtftn, Payload.Method },
{ ILOpCode.Ldarg, Payload.Arg16 },
{ ILOpCode.Ldarga, Payload.Arg16 },
{ ILOpCode.Starg, Payload.Arg16 },
{ ILOpCode.Ldloc, Payload.Local16 },
{ ILOpCode.Ldloca, Payload.Local16 },
{ ILOpCode.Stloc, Payload.Local16 },
{ ILOpCode.Localloc, Payload.None },
{ ILOpCode.Endfilter, Payload.None },
{ ILOpCode.Unaligned, Payload.Ignore8 },
{ ILOpCode.Volatile, Payload.None },
{ ILOpCode.Tail, Payload.None },
{ ILOpCode.Initobj, Payload.TypeTok },
{ ILOpCode.Constrained, Payload.Type },
{ ILOpCode.Cpblk, Payload.None },
{ ILOpCode.Initblk, Payload.None },
{ ILOpCode.Rethrow, Payload.None },
{ ILOpCode.Sizeof, Payload.TypeTok },
{ ILOpCode.Refanytype, Payload.None },
{ ILOpCode.Readonly, Payload.None }
};
public DefinitionMethod Method { get; }
public ILOpCode OpCode { get; }
public int Offset { get; }
public int Index { get; }
private readonly int payloadValue;
private readonly uint unsignedPayloadValue;
public Payload PayloadType
{
get
{
if (!opPayload.TryGetValue(OpCode, out var result))
throw new InternalError("Unknown op code " + OpCode);
return result;
}
}
public override string ToString() => Index + ": " + OpCode;
/// <summary>
/// The number of bytes of this instruction,
/// including the payload (if any).
/// </summary>
public int Width
{
get
{
if (OpCode == ILOpCode.Switch)
return 5 + 4 * payloadValue;
return ((int)OpCode > 255 ? 2 : 1) + PayloadSize;
}
}
private readonly byte[] data;
private int PayloadSize => payloadSizes[(int)PayloadType];
/// <summary>
/// Reads the instruction from a byte stream.
/// </summary>
/// <param name="data">The byte stream.</param>
/// <param name="offset">The offset of the instruction.</param>
/// <param name="index">The index of this instruction in the callable.</param>
public Instruction(Context cx, DefinitionMethod method, byte[] data, int offset, int index) : base(cx)
{
Method = method;
Offset = offset;
Index = index;
this.data = data;
int opcode = data[offset];
++offset;
/*
* An opcode is either 1 or 2 bytes, followed by an optional payload depending on the instruction.
* Instructions where the first byte is 0xfe are 2-byte instructions.
*/
if (opcode == 0xfe)
opcode = opcode << 8 | data[offset++];
OpCode = (ILOpCode)opcode;
switch (PayloadSize)
{
case 0:
payloadValue = 0;
break;
case 1:
payloadValue = (sbyte)data[offset];
unsignedPayloadValue = data[offset];
break;
case 2:
payloadValue = BitConverter.ToInt16(data, offset);
unsignedPayloadValue = BitConverter.ToUInt16(data, offset);
break;
case -1: // Switch
case 4:
payloadValue = BitConverter.ToInt32(data, offset);
break;
case 8: // Not handled here.
break;
default:
throw new InternalError("Unhandled CIL instruction Payload");
}
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var offset = Offset;
if (Method.Implementation is null)
{
yield break;
}
yield return Tuples.cil_instruction(this, (int)OpCode, Index, Method.Implementation);
switch (PayloadType)
{
case Payload.String:
yield return Tuples.cil_value(this, Context.MdReader.GetUserString(MetadataTokens.UserStringHandle(payloadValue)));
break;
case Payload.Float32:
yield return Tuples.cil_value(this, BitConverter.ToSingle(data, offset).ToString());
break;
case Payload.Float64:
yield return Tuples.cil_value(this, BitConverter.ToDouble(data, offset).ToString());
break;
case Payload.Int8:
yield return Tuples.cil_value(this, data[offset].ToString());
break;
case Payload.Int16:
yield return Tuples.cil_value(this, BitConverter.ToInt16(data, offset).ToString());
break;
case Payload.Int32:
yield return Tuples.cil_value(this, BitConverter.ToInt32(data, offset).ToString());
break;
case Payload.Int64:
yield return Tuples.cil_value(this, BitConverter.ToInt64(data, offset).ToString());
break;
case Payload.Constructor:
case Payload.Method:
case Payload.MethodRef:
case Payload.Class:
case Payload.TypeTok:
case Payload.Token:
case Payload.Type:
case Payload.Field:
case Payload.ValueType:
{
// A generic EntityHandle.
var handle = MetadataTokens.EntityHandle(payloadValue);
var target = Context.CreateGeneric(Method, handle);
yield return target;
if (target is not null)
{
yield return Tuples.cil_access(this, target);
}
else
{
throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}");
}
break;
}
case Payload.Arg8:
case Payload.Arg16:
if (Method.Parameters is not null)
{
yield return Tuples.cil_access(this, Method.Parameters[(int)unsignedPayloadValue]);
}
break;
case Payload.Local8:
case Payload.Local16:
if (Method.LocalVariables is not null)
{
yield return Tuples.cil_access(this, Method.LocalVariables[(int)unsignedPayloadValue]);
}
break;
case Payload.None:
case Payload.Target8:
case Payload.Target32:
case Payload.Switch:
case Payload.Ignore8:
// These are not handled here.
// Some of these are handled by JumpContents().
break;
case Payload.CallSiteDesc:
{
var handle = MetadataTokens.EntityHandle(payloadValue);
IExtractedEntity? target = null;
try
{
target = Context.CreateGeneric(Method, handle);
}
catch (Exception exc)
{
Context.Extractor.Logger.Log(Util.Logging.Severity.Warning, $"Couldn't interpret payload of payload type {PayloadType} as a function pointer type. {exc.Message} {exc.StackTrace}");
}
if (target is not null)
{
yield return target;
yield return Tuples.cil_access(this, target);
}
else
{
throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}");
}
break;
}
default:
throw new InternalError($"Unhandled payload type {PayloadType}");
}
}
}
// Called to populate the jumps in each instruction.
public IEnumerable<IExtractionProduct> JumpContents(Dictionary<int, Instruction> jump_table)
{
int target;
Instruction? inst;
switch (PayloadType)
{
case Payload.Target8:
target = Offset + payloadValue + 2;
break;
case Payload.Target32:
target = Offset + payloadValue + 5;
break;
case Payload.Switch:
var end = Offset + Width;
var offset = Offset + 5;
for (var b = 0; b < payloadValue; ++b, offset += 4)
{
target = BitConverter.ToInt32(data, offset) + end;
if (jump_table.TryGetValue(target, out inst))
{
yield return Tuples.cil_switch(this, b, inst);
}
else
{
throw new InternalError("Invalid jump target");
}
}
yield break;
default:
// Not a jump
yield break;
}
if (jump_table.TryGetValue(target, out inst))
{
yield return Tuples.cil_jump(this, inst);
}
else
{
// Sometimes instructions can jump outside the current method.
// TODO: Find a solution to this.
// For now, just log the error
Context.ExtractionError("A CIL instruction jumps outside the current method", null, Extraction.Entities.GeneratedLocation.Create(Context), "", Util.Logging.Severity.Warning);
}
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal class LocalVariable : LabelledEntity
{
private readonly MethodImplementation method;
private readonly int index;
private readonly Type type;
public LocalVariable(Context cx, MethodImplementation m, int i, Type t) : base(cx)
{
method = m;
index = i;
type = t;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(method);
trapFile.Write('_');
trapFile.Write(index);
trapFile.Write(";cil-local");
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return type;
yield return Tuples.cil_local_variable(this, method, index, type);
}
}
}
}

View File

@@ -1,42 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class MemberReferenceField : Field
{
private readonly MemberReferenceHandle handle;
private readonly MemberReference mr;
private readonly IGenericContext gc;
private readonly Type declType;
public MemberReferenceField(IGenericContext gc, MemberReferenceHandle handle) : base(gc.Context)
{
this.handle = handle;
this.gc = gc;
mr = Context.MdReader.GetMemberReference(handle);
declType = (Type)Context.CreateGeneric(gc, mr.Parent);
}
public override bool Equals(object? obj)
{
return obj is MemberReferenceField field && handle.Equals(field.handle);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override string Name => Context.GetString(mr.Name);
public override Type DeclaringType => declType;
public override Type Type => mr.DecodeFieldSignature(Context.TypeSignatureDecoder, this);
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(declType.TypeParameters);
public override IEnumerable<Type> MethodParameters => gc.MethodParameters.Concat(declType.MethodParameters);
}
}

View File

@@ -1,95 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// This is a late-bound reference to a method.
/// </summary>
internal sealed class MemberReferenceMethod : Method
{
private readonly MemberReferenceHandle handle;
private readonly MemberReference mr;
private readonly Type declaringType;
private readonly IGenericContext parent;
private readonly Method? sourceDeclaration;
public MemberReferenceMethod(IGenericContext gc, MemberReferenceHandle handle) : base(gc)
{
this.handle = handle;
this.gc = gc;
mr = Context.MdReader.GetMemberReference(handle);
signature = mr.DecodeMethodSignature(new SignatureDecoder(), gc);
parent = (IGenericContext)Context.CreateGeneric(gc, mr.Parent);
var declType = parent is Method parentMethod
? parentMethod.DeclaringType
: parent as Type;
if (declType is null)
throw new InternalError("Parent context of method is not a type");
declaringType = declType;
nameLabel = Context.GetString(mr.Name);
var typeSourceDeclaration = declaringType.SourceDeclaration;
sourceDeclaration = typeSourceDeclaration == declaringType ? (Method)this : typeSourceDeclaration.LookupMethod(mr.Name, mr.Signature);
}
private readonly string nameLabel;
public override string NameLabel => nameLabel;
public override bool Equals(object? obj)
{
return obj is MemberReferenceMethod method && handle.Equals(method.handle);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override Method? SourceDeclaration => sourceDeclaration;
public override bool IsStatic => !signature.Header.IsInstance;
public override Type DeclaringType => declaringType;
public override string Name => Context.ShortName(mr.Name);
public override IEnumerable<Type> TypeParameters => parent.TypeParameters.Concat(gc.TypeParameters);
public override IEnumerable<IExtractionProduct> Contents
{
get
{
genericParams = new MethodTypeParameter[signature.GenericParameterCount];
for (var p = 0; p < genericParams.Length; ++p)
genericParams[p] = Context.Populate(new MethodTypeParameter(this, this, p));
foreach (var p in genericParams)
yield return p;
var typeSignature = mr.DecodeMethodSignature(Context.TypeSignatureDecoder, this);
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var p in parameters) yield return p;
foreach (var f in PopulateFlags) yield return f;
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType))
{
yield return m;
}
if (SourceDeclaration is not null)
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
}
}
}
}

View File

@@ -1,131 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A method entity.
/// </summary>
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
{
protected MethodTypeParameter[]? genericParams;
protected IGenericContext gc;
protected MethodSignature<ITypeSignature> signature;
protected Method(IGenericContext gc) : base(gc.Context)
{
this.gc = gc;
}
public ITypeSignature ReturnType => signature.ReturnType;
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
public override IEnumerable<Type> MethodParameters =>
genericParams is null ? gc.MethodParameters : gc.MethodParameters.Concat(genericParams);
public int GenericParameterCount => signature.GenericParameterCount;
public virtual Method? SourceDeclaration => this;
public abstract Type DeclaringType { get; }
public abstract string Name { get; }
public virtual IList<LocalVariable>? LocalVariables => throw new NotImplementedException();
public IList<Parameter>? Parameters { get; protected set; }
public abstract string NameLabel { get; }
public override void WriteId(EscapingTextWriter trapFile)
{
signature.ReturnType.WriteId(trapFile, this);
trapFile.Write(' ');
DeclaringType.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(NameLabel);
if (signature.GenericParameterCount > 0)
{
trapFile.Write('`');
trapFile.Write(signature.GenericParameterCount);
}
trapFile.Write('(');
var index = 0;
foreach (var param in signature.ParameterTypes)
{
trapFile.WriteSeparator(",", ref index);
param.WriteId(trapFile, this);
}
trapFile.Write(");cil-method");
}
protected IEnumerable<IExtractionProduct> PopulateFlags
{
get
{
if (IsStatic)
yield return Tuples.cil_static(this);
}
}
public abstract bool IsStatic { get; }
protected IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes)
{
var i = 0;
if (!IsStatic)
{
yield return Context.Populate(new Parameter(Context, this, i++, DeclaringType));
}
foreach (var p in GetParameterExtractionProducts(parameterTypes, this, this, Context, i))
{
yield return p;
}
}
internal static IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes, IParameterizable parameterizable, ICustomModifierReceiver receiver, Context cx, int firstChildIndex)
{
var i = firstChildIndex;
foreach (var p in parameterTypes)
{
var t = p;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(receiver, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
var parameter = cx.Populate(new Parameter(cx, parameterizable, i++, t));
yield return parameter;
yield return Tuples.cil_type_annotation(parameter, TypeAnnotation.Ref);
}
else
{
yield return cx.Populate(new Parameter(cx, parameterizable, i++, t));
}
}
}
protected IEnumerable<IExtractionProduct> GetMethodExtractionProducts(string name, Type declaringType, Type returnType)
{
var t = returnType;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_method(this, name, declaringType, t);
}
}
}

View File

@@ -1,26 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A method implementation entity.
/// In the database, the same method could in principle have multiple implementations.
/// </summary>
internal class MethodImplementation : UnlabelledEntity
{
private readonly Method m;
public MethodImplementation(Method m) : base(m.Context)
{
this.m = m;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_method_implementation(this, m, Context.Assembly);
}
}
}
}

View File

@@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A constructed method.
/// </summary>
internal sealed class MethodSpecificationMethod : Method
{
private readonly MethodSpecificationHandle handle;
private readonly MethodSpecification ms;
private readonly Method unboundMethod;
private readonly ImmutableArray<Type> typeParams;
public MethodSpecificationMethod(IGenericContext gc, MethodSpecificationHandle handle) : base(gc)
{
this.handle = handle;
ms = Context.MdReader.GetMethodSpecification(handle);
typeParams = ms.DecodeSignature(Context.TypeSignatureDecoder, gc);
unboundMethod = (Method)Context.CreateGeneric(gc, ms.Method);
}
public override void WriteId(EscapingTextWriter trapFile)
{
unboundMethod.WriteId(trapFile);
trapFile.Write('<');
var index = 0;
foreach (var param in typeParams)
{
trapFile.WriteSeparator(",", ref index);
trapFile.WriteSubId(param);
}
trapFile.Write('>');
}
public override string NameLabel => throw new NotImplementedException();
public override bool Equals(object? obj)
{
return obj is MethodSpecificationMethod method && handle.Equals(method.handle) && typeParams.SequenceEqual(method.typeParams);
}
public override int GetHashCode() => handle.GetHashCode() * 11 + typeParams.SequenceHash();
public override Method SourceDeclaration => unboundMethod;
public override Type DeclaringType => unboundMethod.DeclaringType;
public override string Name => unboundMethod.Name;
public override bool IsStatic => unboundMethod.IsStatic;
public override IEnumerable<Type> MethodParameters => typeParams;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
MethodSignature<Type> constructedTypeSignature;
switch (ms.Method.Kind)
{
case HandleKind.MemberReference:
var mr = Context.MdReader.GetMemberReference((MemberReferenceHandle)ms.Method);
constructedTypeSignature = mr.DecodeMethodSignature(Context.TypeSignatureDecoder, this);
break;
case HandleKind.MethodDefinition:
var md = Context.MdReader.GetMethodDefinition((MethodDefinitionHandle)ms.Method);
constructedTypeSignature = md.DecodeSignature(Context.TypeSignatureDecoder, this);
break;
default:
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
}
var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var p in parameters)
yield return p;
foreach (var f in PopulateFlags)
yield return f;
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, constructedTypeSignature.ReturnType))
{
yield return m;
}
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
if (typeParams.Length != unboundMethod.GenericParameterCount)
throw new InternalError("Method type parameter mismatch");
for (var p = 0; p < typeParams.Length; ++p)
{
yield return Tuples.cil_type_argument(this, p, typeParams[p]);
}
}
}
}
}

View File

@@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class MethodTypeParameter : TypeParameter
{
private readonly Method method;
private readonly int index;
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
if (!(inContext && method == gc))
{
trapFile.WriteSubId(method);
}
trapFile.Write("!");
trapFile.Write(index);
}
public override string Name => "!" + index;
public MethodTypeParameter(IGenericContext gc, Method m, int index) : base(gc)
{
method = m;
this.index = index;
}
public override bool Equals(object? obj)
{
return obj is MethodTypeParameter tp && method.Equals(tp.method) && index == tp.index;
}
public override int GetHashCode()
{
return method.GetHashCode() * 29 + index;
}
public override TypeContainer Parent => method;
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_type(this, Name, Kind, method, SourceDeclaration);
yield return Tuples.cil_type_parameter(method, index, this);
}
}
}
}

View File

@@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Modified types are not written directly to trap files. Instead, the modifiers are stored
/// on the modifiable entity (field type, property/method/function pointer parameter or return types).
/// </summary>
internal sealed class ModifiedType : Type
{
public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired) : base(cx)
{
Unmodified = unmodified;
Modifier = modifier;
IsRequired = isRequired;
}
public Type Unmodified { get; }
public Type Modifier { get; }
public bool IsRequired { get; }
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{Unmodified.Name} {(IsRequired ? "modreq" : "modopt")}({Modifier.Name})";
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
Unmodified.WriteId(trapFile, inContext);
trapFile.Write(IsRequired ? " modreq" : " modopt");
trapFile.Write("(");
Modifier.WriteId(trapFile, inContext);
trapFile.Write(")");
}
}
}

View File

@@ -1,61 +0,0 @@
using System.Linq;
namespace Semmle.Extraction.CIL.Entities
{
internal class NamedTypeIdWriter
{
private readonly Type type;
public NamedTypeIdWriter(Type type)
{
this.type = type;
}
public void WriteId(EscapingTextWriter trapFile, bool inContext)
{
if (type.IsPrimitiveType)
{
Type.WritePrimitiveTypeId(trapFile, type.Name);
return;
}
var ct = type.ContainingType;
if (ct is not null)
{
ct.WriteId(trapFile, inContext);
trapFile.Write('.');
}
else
{
type.WriteAssemblyPrefix(trapFile);
var ns = type.ContainingNamespace!;
if (!ns.IsGlobalNamespace)
{
ns.WriteId(trapFile);
trapFile.Write('.');
}
}
trapFile.Write(type.Name);
var thisTypeArguments = type.ThisTypeArguments;
if (thisTypeArguments is not null && thisTypeArguments.Any())
{
trapFile.Write('<');
var index = 0;
foreach (var t in thisTypeArguments)
{
trapFile.WriteSeparator(",", ref index);
t.WriteId(trapFile);
}
trapFile.Write('>');
}
else if (type.ThisTypeParameterCount > 0)
{
trapFile.Write('`');
trapFile.Write(type.ThisTypeParameterCount);
}
}
}
}

View File

@@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A namespace.
/// </summary>
internal sealed class Namespace : TypeContainer
{
public Namespace? ParentNamespace { get; }
public string Name { get; }
public bool IsGlobalNamespace => ParentNamespace is null;
public override void WriteId(EscapingTextWriter trapFile)
{
if (ParentNamespace is not null && !ParentNamespace.IsGlobalNamespace)
{
ParentNamespace.WriteId(trapFile);
trapFile.Write('.');
}
trapFile.Write(Name);
trapFile.Write(";namespace");
}
public override bool Equals(object? obj)
{
if (obj is Namespace ns && Name == ns.Name)
{
if (ParentNamespace is null)
return ns.ParentNamespace is null;
if (!(ns.ParentNamespace is null))
return ParentNamespace.Equals(ns.ParentNamespace);
}
return false;
}
public override int GetHashCode()
{
var h = ParentNamespace is null ? 19 : ParentNamespace.GetHashCode();
return 13 * h + Name.GetHashCode();
}
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override IEnumerable<Type> MethodParameters => throw new NotImplementedException();
private static string parseNamespaceName(string fqn)
{
var i = fqn.LastIndexOf('.');
return i == -1 ? fqn : fqn.Substring(i + 1);
}
private static Namespace? createParentNamespace(Context cx, string fqn)
{
if (fqn.Length == 0)
return null;
var i = fqn.LastIndexOf('.');
return i == -1 ? cx.GlobalNamespace : cx.Populate(new Namespace(cx, fqn.Substring(0, i)));
}
public Namespace(Context cx, string fqn) : this(cx, parseNamespaceName(fqn), createParentNamespace(cx, fqn))
{
}
public Namespace(Context cx, string name, Namespace? parent) : base(cx)
{
Name = name;
ParentNamespace = parent;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.namespaces(this, Name);
if (ParentNamespace is not null)
yield return Tuples.parent_namespace(this, ParentNamespace);
}
}
}
}

View File

@@ -1,162 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed partial class NoMetadataHandleType
{
/// <summary>
/// Parser to split a fully qualified name into short name, namespace or declaring type name, assembly name, and
/// type argument names. Names are in the following format:
/// <c>N1.N2.T1`2+T2`2[T3,[T4, A1, Version=...],T5,T6], A2, Version=...</c>
/// </summary>
/// <example>
/// <code>typeof(System.Collections.Generic.List<int>.Enumerator)
/// -> System.Collections.Generic.List`1+Enumerator[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
/// typeof(System.Collections.Generic.List<>.Enumerator)
/// -> System.Collections.Generic.List`1+Enumerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
/// </code>
/// </example>
private class FullyQualifiedNameParser
{
public string ShortName { get; internal set; }
public string? AssemblyName { get; private set; }
public IEnumerable<string>? TypeArguments { get; internal set; }
public string? UnboundGenericTypeName { get; internal set; }
public string ContainerName { get; internal set; }
public bool IsContainerNamespace { get; internal set; }
private string AssemblySuffix => string.IsNullOrWhiteSpace(AssemblyName) ? "" : $", {AssemblyName}";
public FullyQualifiedNameParser(string name)
{
ExtractAssemblyName(ref name, out var lastBracketIndex);
ExtractTypeArguments(ref name, lastBracketIndex, out var containerTypeArguments);
ContainerName = ExtractContainer(ref name, containerTypeArguments);
ShortName = name;
}
private void ExtractTypeArguments(ref string name, int lastBracketIndex, out string containerTypeArguments)
{
var firstBracketIndex = name.IndexOf('[');
if (firstBracketIndex < 0)
{
// not generic or non-constructed generic
TypeArguments = null;
containerTypeArguments = "";
UnboundGenericTypeName = null;
return;
}
// "T3,[T4, Assembly1, Version=...],T5,T6"
string typeArgs;
(name, _, typeArgs, _) = name.Split(firstBracketIndex, firstBracketIndex + 1, lastBracketIndex);
var thisTypeArgCount = GenericsHelper.GetGenericTypeParameterCount(name);
if (thisTypeArgCount == 0)
{
// not generic or non-constructed generic; container is constructed
TypeArguments = null;
containerTypeArguments = $"[{typeArgs}]";
UnboundGenericTypeName = null;
return;
}
// constructed generic
// "T3,[T4, Assembly1, Version=...]", ["T5", "T6"]
var (containerTypeArgs, thisTypeArgs) = ParseTypeArgumentStrings(typeArgs, thisTypeArgCount);
TypeArguments = thisTypeArgs;
containerTypeArguments = string.IsNullOrWhiteSpace(containerTypeArgs)
? "" // containing type is not constructed generics
: $"[{containerTypeArgs}]"; // "T3,[T4, Assembly1, Version=...],,]"
UnboundGenericTypeName = $"{name}{AssemblySuffix}";
}
private string ExtractContainer(ref string name, string containerTypeArguments)
{
var lastPlusIndex = name.LastIndexOf('+');
IsContainerNamespace = lastPlusIndex < 0;
if (IsContainerNamespace)
{
return ExtractContainerNamespace(ref name);
}
return ExtractContainerType(ref name, containerTypeArguments, lastPlusIndex);
}
private static string ExtractContainerNamespace(ref string name)
{
var lastDotIndex = name.LastIndexOf('.');
if (lastDotIndex >= 0)
{
string containerName;
(containerName, _, name) = name.Split(lastDotIndex, lastDotIndex + 1);
return containerName;
}
return ""; // global namespace name
}
private string ExtractContainerType(ref string name, string containerTypeArguments, int lastPlusIndex)
{
string containerName;
(containerName, _, name) = name.Split(lastPlusIndex, lastPlusIndex + 1);
return $"{containerName}{containerTypeArguments}{AssemblySuffix}";
}
private void ExtractAssemblyName(ref string name, out int lastBracketIndex)
{
lastBracketIndex = name.LastIndexOf(']');
var assemblyCommaIndex = name.IndexOf(',', lastBracketIndex < 0 ? 0 : lastBracketIndex);
if (assemblyCommaIndex >= 0)
{
// "Assembly2, Version=..."
(name, _, AssemblyName) = name.Split(assemblyCommaIndex, assemblyCommaIndex + 2);
}
}
private static (string, IEnumerable<string>) ParseTypeArgumentStrings(string typeArgs, int thisTypeArgCount)
{
var thisTypeArgs = new Stack<string>(thisTypeArgCount);
while (typeArgs.Length > 0 && thisTypeArgCount > 0)
{
int startCurrentType;
if (typeArgs[^1] != ']')
{
startCurrentType = typeArgs.LastIndexOf(',') + 1;
thisTypeArgs.Push(typeArgs.Substring(startCurrentType));
}
else
{
var bracketCount = 1;
for (startCurrentType = typeArgs.Length - 2; startCurrentType >= 0 && bracketCount > 0; startCurrentType--)
{
if (typeArgs[startCurrentType] == ']')
{
bracketCount++;
}
else if (typeArgs[startCurrentType] == '[')
{
bracketCount--;
}
}
startCurrentType++;
thisTypeArgs.Push(typeArgs[(startCurrentType + 1)..^1]);
}
typeArgs = startCurrentType != 0
? typeArgs.Substring(0, startCurrentType - 1)
: "";
thisTypeArgCount--;
}
return (typeArgs, thisTypeArgs.ToList());
}
}
}
}

View File

@@ -1,161 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed partial class NoMetadataHandleType : Type
{
private readonly string originalName;
private readonly string name;
private readonly string? assemblyName;
private readonly string containerName;
private readonly bool isContainerNamespace;
private readonly Lazy<TypeTypeParameter[]>? typeParams;
// Either null or notEmpty
private readonly Type[]? thisTypeArguments;
private readonly Type unboundGenericType;
private readonly Type? containingType;
private readonly Namespace? containingNamespace;
private readonly NamedTypeIdWriter idWriter;
public NoMetadataHandleType(Context cx, string originalName) : base(cx)
{
this.originalName = originalName;
this.idWriter = new NamedTypeIdWriter(this);
var nameParser = new FullyQualifiedNameParser(originalName);
name = nameParser.ShortName;
assemblyName = nameParser.AssemblyName;
isContainerNamespace = nameParser.IsContainerNamespace;
containerName = nameParser.ContainerName;
unboundGenericType = nameParser.UnboundGenericTypeName is null
? this
: new NoMetadataHandleType(Context, nameParser.UnboundGenericTypeName);
if (nameParser.TypeArguments is not null)
{
thisTypeArguments = nameParser.TypeArguments.Select(t => new NoMetadataHandleType(Context, t)).ToArray();
}
else
{
typeParams = new Lazy<TypeTypeParameter[]>(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount));
}
containingType = isContainerNamespace
? null
: new NoMetadataHandleType(Context, containerName);
containingNamespace = isContainerNamespace
? containerName == Context.GlobalNamespace.Name
? Context.GlobalNamespace
: containerName == Context.SystemNamespace.Name
? Context.SystemNamespace
: new Namespace(Context, containerName)
: null;
Populate();
}
private void Populate()
{
if (ContainingNamespace is not null)
{
Context.Populate(ContainingNamespace);
}
Context.Populate(this);
}
public override bool Equals(object? obj)
{
return obj is NoMetadataHandleType t && originalName.Equals(t.originalName, StringComparison.Ordinal);
}
public override int GetHashCode()
{
return originalName.GetHashCode(StringComparison.Ordinal);
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var tp in typeParams?.Value ?? Array.Empty<TypeTypeParameter>())
yield return tp;
foreach (var c in base.Contents)
yield return c;
var i = 0;
foreach (var type in ThisTypeArguments)
{
yield return type;
yield return Tuples.cil_type_argument(this, i++, type);
}
}
}
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override string Name => GenericsHelper.GetNonGenericName(name);
public override Namespace? ContainingNamespace => containingNamespace;
public override Type? ContainingType => containingType;
public override Type SourceDeclaration => unboundGenericType;
public override Type Construct(IEnumerable<Type> typeArguments)
{
if (TotalTypeParametersCount != typeArguments.Count())
throw new InternalError("Mismatched type arguments");
return Context.Populate(new ConstructedType(Context, this, typeArguments));
}
public override void WriteAssemblyPrefix(TextWriter trapFile)
{
if (!string.IsNullOrWhiteSpace(assemblyName))
{
var an = new AssemblyName(assemblyName);
trapFile.Write(an.Name);
trapFile.Write('_');
trapFile.Write((an.Version ?? new Version(0, 0, 0, 0)).ToString());
trapFile.Write(Type.AssemblyTypeNameSeparator);
}
else
{
Context.WriteAssemblyPrefix(trapFile);
}
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}
public override int ThisTypeParameterCount => unboundGenericType == this
? GenericsHelper.GetGenericTypeParameterCount(name)
: thisTypeArguments!.Length;
public override IEnumerable<Type> TypeParameters => unboundGenericType == this
? GenericsHelper.GetAllTypeParameters(containingType, typeParams!.Value)
: GenericArguments;
public override IEnumerable<Type> ThisTypeArguments => unboundGenericType == this
? base.ThisTypeArguments
: thisTypeArguments!;
public override IEnumerable<Type> ThisGenericArguments => unboundGenericType == this
? typeParams!.Value
: thisTypeArguments!;
}
}

View File

@@ -1,47 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A parameter entity.
/// </summary>
internal sealed class Parameter : LabelledEntity
{
private readonly IParameterizable parameterizable;
private readonly int index;
private readonly Type type;
public Parameter(Context cx, IParameterizable p, int i, Type t) : base(cx)
{
parameterizable = p;
index = i;
type = t;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(parameterizable);
trapFile.Write('_');
trapFile.Write(index);
trapFile.Write(";cil-parameter");
}
public override bool Equals(object? obj)
{
return obj is Parameter param && parameterizable.Equals(param.parameterizable) && index == param.index;
}
public override int GetHashCode()
{
return 23 * parameterizable.GetHashCode() + index;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_parameter(this, parameterizable, index, type);
}
}
}
}

View File

@@ -1,32 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal class PdbSourceFile : File
{
private readonly PDB.ISourceFile file;
public PdbSourceFile(Context cx, PDB.ISourceFile file) : base(cx, file.Path)
{
this.file = file;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
yield return c;
var text = file.Contents;
if (text is null)
Context.Extractor.Logger.Log(Util.Logging.Severity.Warning, string.Format("PDB source file {0} could not be found", OriginalPath));
else
Context.TrapWriter.Archive(TransformedPath, text);
yield return Tuples.file_extraction_mode(this, Context.Extractor.Mode | ExtractorMode.Pdb);
}
}
}
}

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class PointerType : Type
{
private readonly Type pointee;
public PointerType(Context cx, Type pointee) : base(cx)
{
this.pointee = pointee;
if (pointee is ModifiedType mt)
{
cx.Extractor.Logger.Log(
Util.Logging.Severity.Info,
$"Pointer to modified type {pointee.GetQualifiedName()} is changed to {mt.Unmodified.GetQualifiedName()}");
this.pointee = mt.Unmodified;
}
}
public override bool Equals(object? obj)
{
return obj is PointerType pt && pointee.Equals(pt.pointee);
}
public override int GetHashCode() => HashCode.Combine(pointee, nameof(PointerType));
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
pointee.WriteId(trapFile, inContext);
trapFile.Write('*');
}
public override string Name => pointee.Name + "*";
public override Namespace? ContainingNamespace => pointee.ContainingNamespace;
public override Type? ContainingType => pointee.ContainingType;
public override TypeContainer Parent => pointee.Parent;
public override int ThisTypeParameterCount => 0;
public override CilTypeKind Kind => CilTypeKind.Pointer;
public override void WriteAssemblyPrefix(TextWriter trapFile) => pointee.WriteAssemblyPrefix(trapFile);
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents) yield return c;
yield return Tuples.cil_pointer_type(this, pointee);
}
}
}
}

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