mirror of
https://github.com/github/codeql.git
synced 2026-04-27 09:45:15 +02:00
Work on classes + refactor
Began working o inheritance, polymorphism and constructor init. Correct code is produced for them (though some more work is needed to accurately treat conversions between classes). Removed commented code. Added classes to properly deal with constructor init and modified and refactored TranslatedFunction to accomodate for the changes.
This commit is contained in:
@@ -25,6 +25,7 @@ newtype TInstructionTag =
|
||||
AssignOperationLoadTag() or
|
||||
AssignOperationConvertLeftTag() or
|
||||
AssignOperationOpTag() or
|
||||
AssignmentConvertRightTag() or
|
||||
AssignOperationConvertResultTag() or
|
||||
AssignmentStoreTag() or
|
||||
CrementLoadTag() or
|
||||
@@ -114,6 +115,7 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or
|
||||
tag = AssignOperationLoadTag() and result = "AssignOpLoad" or
|
||||
tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or
|
||||
tag = AssignmentConvertRightTag() and result = "AssignConvRight" or
|
||||
tag = AssignOperationOpTag() and result = "AssignOpOp" or
|
||||
tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or
|
||||
tag = AssignmentStoreTag() and result = "AssignStore" or
|
||||
|
||||
@@ -278,7 +278,10 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
|
||||
* the constructor call, address will be passed to a variable declaration.
|
||||
*/
|
||||
class TranslatedConstructorCall extends TranslatedFunctionCall {
|
||||
TranslatedConstructorCall() { expr instanceof ObjectCreation }
|
||||
TranslatedConstructorCall() {
|
||||
expr instanceof ObjectCreation or
|
||||
expr instanceof ConstructorInitializer
|
||||
}
|
||||
|
||||
override Instruction getQualifierResult() {
|
||||
exists(StructorCallContext context |
|
||||
|
||||
@@ -307,19 +307,10 @@ newtype TTranslatedElement =
|
||||
isFirstValueInitializedElementInRange(initList, elementIndex) and
|
||||
elementCount = getEndOfValueInitializedRange(initList, elementIndex) - elementIndex
|
||||
} or
|
||||
// TODO: Convert to C#
|
||||
// The initialization of a base class from within a constructor.
|
||||
// TTranslatedConstructorBaseInit(ConstructorBaseInit init) {
|
||||
// not ignoreExpr(init)
|
||||
// } or
|
||||
// // The destruction of a base class from within a destructor.
|
||||
// TTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) {
|
||||
// not ignoreExpr(destruction)
|
||||
// } or
|
||||
// // The destruction of a field from within a destructor.
|
||||
// TTranslatedDestructorFieldDestruction(DestructorFieldDestruction destruction) {
|
||||
// not ignoreExpr(destruction)
|
||||
// } or
|
||||
// The initialization of a base class from within a constructor.
|
||||
TTranslatedConstructorInitializer(ConstructorInitializer init) {
|
||||
not ignoreExpr(init)
|
||||
} or
|
||||
// A statement
|
||||
TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or
|
||||
// A function
|
||||
|
||||
@@ -1507,19 +1507,22 @@ abstract class TranslatedAssignment extends TranslatedNonConstantExpr {
|
||||
result = getRightOperand().getFirstInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
(
|
||||
needsConversion() and
|
||||
tag = AssignmentConvertRightTag() and
|
||||
// For now only use `Opcode::Convert` to
|
||||
// crudely represent conversions. Could
|
||||
// be useful to represent the whole chain of conversions
|
||||
opcode instanceof Opcode::Convert and
|
||||
resultType = expr.getLValue().getType() and
|
||||
isLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override final Instruction getResult() {
|
||||
//if expr.isPRValueCategory() then (
|
||||
// If this is C, then the result of an assignment is a prvalue for the new
|
||||
// value assigned to the left operand. If this is C++, then the result is
|
||||
// an lvalue, but that lvalue is being loaded as part of this expression.
|
||||
// EDG doesn't mark this as a load.
|
||||
result = getStoredValue()
|
||||
//)
|
||||
//else (
|
||||
// This is C++, where the result is an lvalue for the left operand,
|
||||
// and that lvalue is not being loaded as part of this expression.
|
||||
//result = getLeftOperand().getResult()
|
||||
//)
|
||||
}
|
||||
|
||||
abstract Instruction getStoredValue();
|
||||
@@ -1531,6 +1534,10 @@ abstract class TranslatedAssignment extends TranslatedNonConstantExpr {
|
||||
final TranslatedExpr getRightOperand() {
|
||||
result = getTranslatedExpr(expr.getRValue())
|
||||
}
|
||||
|
||||
final predicate needsConversion() {
|
||||
expr.getLValue().getType() != expr.getRValue().getType()
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedAssignExpr extends TranslatedAssignment {
|
||||
@@ -1543,16 +1550,27 @@ class TranslatedAssignExpr extends TranslatedAssignment {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
EdgeKind kind) {
|
||||
tag = AssignmentStoreTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
(
|
||||
tag = AssignmentStoreTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
) or
|
||||
(
|
||||
needsConversion() and
|
||||
tag = AssignmentConvertRightTag() and
|
||||
result = getLeftOperand().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// Operands are evaluated right-to-left.
|
||||
(
|
||||
child = getRightOperand() and
|
||||
result = getLeftOperand().getFirstInstruction()
|
||||
if (needsConversion()) then
|
||||
result = getInstruction(AssignmentConvertRightTag())
|
||||
else
|
||||
result = getLeftOperand().getFirstInstruction()
|
||||
) or
|
||||
(
|
||||
child = getLeftOperand() and
|
||||
@@ -1562,24 +1580,37 @@ class TranslatedAssignExpr extends TranslatedAssignment {
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
tag = AssignmentStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType() and
|
||||
isLValue = false
|
||||
TranslatedAssignment.super.hasInstruction(opcode, tag, resultType, isLValue) or
|
||||
(
|
||||
tag = AssignmentStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getResultType() and
|
||||
isLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag,
|
||||
OperandTag operandTag) {
|
||||
tag = AssignmentStoreTag() and
|
||||
(
|
||||
tag = AssignmentStoreTag() and
|
||||
(
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getLeftOperand().getResult()
|
||||
) or
|
||||
(
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
if (needsConversion()) then
|
||||
result = getInstruction(AssignmentConvertRightTag())
|
||||
else
|
||||
result = getRightOperand().getResult()
|
||||
)
|
||||
)
|
||||
) or
|
||||
(
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getLeftOperand().getResult()
|
||||
) or
|
||||
(
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getRightOperand().getResult()
|
||||
)
|
||||
tag = AssignmentConvertRightTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getRightOperand().getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2016,67 +2047,6 @@ abstract class StructorCallContext extends TranslatedElement {
|
||||
abstract Instruction getReceiver();
|
||||
}
|
||||
|
||||
// TODO: Reason about how to translate destructors in C# (finalizers + dispose)
|
||||
///**
|
||||
// * Represents the IR translation of the destruction of a field from within
|
||||
// * the destructor of the field's declaring class.
|
||||
// */
|
||||
//class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr,
|
||||
// StructorCallContext {
|
||||
// override DestructorFieldDestruction expr;
|
||||
//
|
||||
// override final TranslatedElement getChild(int id) {
|
||||
// id = 0 and result = getDestructorCall()
|
||||
// }
|
||||
//
|
||||
// override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
// Type resultType, boolean ) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// opcode instanceof Opcode::FieldAddress and
|
||||
// resultType = expr.getTarget().getUnspecifiedType() and
|
||||
// = true
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
// EdgeKind kind) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// kind instanceof GotoEdge and
|
||||
// result = getDestructorCall().getFirstInstruction()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// child = getDestructorCall() and
|
||||
// result = getParent().getChildSuccessor(this)
|
||||
// }
|
||||
//
|
||||
// override final Instruction getResult() {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getFirstInstruction() {
|
||||
// result = getInstruction(OnlyInstructionTag())
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// operandTag instanceof UnaryOperandTag and
|
||||
// result = getTranslatedFunction(expr.getEnclosingFunction()).getInitializeThisInstruction()
|
||||
// }
|
||||
//
|
||||
// override final Field getInstructionField(InstructionTag tag) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// result = expr.getTarget()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getReceiver() {
|
||||
// result = getInstruction(OnlyInstructionTag())
|
||||
// }
|
||||
//
|
||||
// private TranslatedExpr getDestructorCall() {
|
||||
// result = getTranslatedExpr(expr.getExpr())
|
||||
// }
|
||||
// }
|
||||
|
||||
class TranslatedConditionalExpr extends TranslatedNonConstantExpr,
|
||||
ConditionContext {
|
||||
override ConditionalExpr expr;
|
||||
@@ -2292,374 +2262,6 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr,
|
||||
}
|
||||
}
|
||||
|
||||
///**
|
||||
// * IR translation of a `throw` expression.
|
||||
// */
|
||||
//abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr {
|
||||
// override ThrowExpr expr;
|
||||
//
|
||||
// override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
// Type resultType, boolean isLValue) {
|
||||
// tag = ThrowTag() and
|
||||
// opcode = getThrowOpcode() and
|
||||
// resultType instanceof VoidType and
|
||||
// isLValue = false
|
||||
// }
|
||||
//
|
||||
// override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
// EdgeKind kind) {
|
||||
// tag = ThrowTag() and
|
||||
// kind instanceof ExceptionEdge and
|
||||
// result = getParent().getExceptionSuccessorInstruction()
|
||||
// }
|
||||
//
|
||||
// override Instruction getResult() {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// abstract Opcode getThrowOpcode();
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * IR translation of a `throw` expression with an argument
|
||||
// * (e.g. `throw std::bad_alloc()`).
|
||||
// */
|
||||
//class TranslatedThrowValueExpr extends TranslatedThrowExpr,
|
||||
// InitializationContext {
|
||||
// TranslatedThrowValueExpr() {
|
||||
// not expr instanceof ThrowExpr
|
||||
// }
|
||||
//
|
||||
// override TranslatedElement getChild(int id) {
|
||||
// id = 0 and result = getInitialization()
|
||||
// }
|
||||
//
|
||||
// override Instruction getFirstInstruction() {
|
||||
// result = getInstruction(InitializerVariableAddressTag())
|
||||
// }
|
||||
//
|
||||
// override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
// Type resultType, boolean isLValue) {
|
||||
// TranslatedThrowExpr.super.hasInstruction(opcode, tag, resultType, isLValue) or
|
||||
// tag = InitializerVariableAddressTag() and
|
||||
// opcode instanceof Opcode::VariableAddress and
|
||||
// resultType = getExceptionType() and
|
||||
// isLValue = true
|
||||
// }
|
||||
//
|
||||
// override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
// EdgeKind kind) {
|
||||
// result = TranslatedThrowExpr.super.getInstructionSuccessor(tag, kind) or
|
||||
// (
|
||||
// tag = InitializerVariableAddressTag() and
|
||||
// result = getInitialization().getFirstInstruction() and
|
||||
// kind instanceof GotoEdge
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// child = getInitialization() and
|
||||
// result = getInstruction(ThrowTag())
|
||||
// }
|
||||
//
|
||||
// override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
// tag = InitializerVariableAddressTag() and
|
||||
// result = getIRTempVariable(expr, ThrowTempVar())
|
||||
// }
|
||||
//
|
||||
// override final predicate hasTempVariable(TempVariableTag tag, Type type) {
|
||||
// tag = ThrowTempVar() and
|
||||
// type = getExceptionType()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionOperand(InstructionTag tag,
|
||||
// OperandTag operandTag) {
|
||||
// tag = ThrowTag() and
|
||||
// (
|
||||
// (
|
||||
// operandTag instanceof AddressOperandTag and
|
||||
// result = getInstruction(InitializerVariableAddressTag())
|
||||
// ) or
|
||||
// (
|
||||
// operandTag instanceof LoadOperandTag and
|
||||
// result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// override final Type getInstructionOperandType(InstructionTag tag,
|
||||
// TypedOperandTag operandTag) {
|
||||
// tag = ThrowTag() and
|
||||
// operandTag instanceof LoadOperandTag and
|
||||
// result = getExceptionType()
|
||||
// }
|
||||
//
|
||||
// override Instruction getTargetAddress() {
|
||||
// result = getInstruction(InitializerVariableAddressTag())
|
||||
// }
|
||||
//
|
||||
// override Type getTargetType() {
|
||||
// result = getExceptionType()
|
||||
// }
|
||||
//
|
||||
// TranslatedInitialization getInitialization() {
|
||||
// result = getTranslatedInitialization(
|
||||
// expr.getExpr())
|
||||
// }
|
||||
//
|
||||
// override final Opcode getThrowOpcode() {
|
||||
// result instanceof Opcode::ThrowValue
|
||||
// }
|
||||
//
|
||||
// private Type getExceptionType() {
|
||||
// result = expr.getType()
|
||||
// }
|
||||
//}
|
||||
|
||||
// TODO: Should be handeled by the normal throw in C#
|
||||
///**
|
||||
// * IR translation of a `throw` expression with no argument (e.g. `throw;`).
|
||||
// */
|
||||
//class TranslatedReThrowExpr extends TranslatedThrowExpr {
|
||||
// override ReThrowExpr expr;
|
||||
//
|
||||
// override TranslatedElement getChild(int id) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override Instruction getFirstInstruction() {
|
||||
// result = getInstruction(ThrowTag())
|
||||
// }
|
||||
//
|
||||
// override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override final Opcode getThrowOpcode() {
|
||||
// result instanceof Opcode::ReThrow
|
||||
// }
|
||||
//}
|
||||
|
||||
// TODO: Probably does not have a translation in C#
|
||||
///**
|
||||
// * The IR translation of a built-in operation (i.e. anything that extends
|
||||
// * `BuiltInOperation`).
|
||||
// */
|
||||
//abstract class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
|
||||
// override final Instruction getResult() {
|
||||
// result = getInstruction(OnlyInstructionTag())
|
||||
// }
|
||||
//
|
||||
// override final Instruction getFirstInstruction() {
|
||||
// if exists(getChild(0)) then
|
||||
// result = getChild(0).getFirstInstruction()
|
||||
// else
|
||||
// result = getInstruction(OnlyInstructionTag())
|
||||
// }
|
||||
//
|
||||
// override final TranslatedElement getChild(int id) {
|
||||
// result = getTranslatedExpr(expr.getChild(id))
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
// EdgeKind kind) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// kind instanceof GotoEdge and
|
||||
// result = getParent().getChildSuccessor(this)
|
||||
// }
|
||||
//
|
||||
// override final Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// exists(int id |
|
||||
// child = getChild(id) and
|
||||
// (
|
||||
// result = getChild(id + 1).getFirstInstruction() or
|
||||
// not exists(getChild(id + 1)) and result = getInstruction(OnlyInstructionTag())
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
// Type resultType, boolean isLValue) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// opcode = getOpcode() and
|
||||
// resultType = getResultType() and
|
||||
// isLValue = isResultLValue()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionOperand(InstructionTag tag,
|
||||
// OperandTag operandTag) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// exists(int index |
|
||||
// operandTag = positionalArgumentOperand(index) and
|
||||
// result = getChild(index).(TranslatedExpr).getResult()
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// abstract Opcode getOpcode();
|
||||
//}
|
||||
|
||||
|
||||
// TODO: See how and if we would adapt those to C#
|
||||
///**
|
||||
// * The IR translation of a `BuiltInVarArgsStart` expression.
|
||||
// */
|
||||
//class TranslatedVarArgsStart extends TranslatedBuiltInOperation {
|
||||
// override BuiltInVarArgsStart expr;
|
||||
//
|
||||
// override final Opcode getOpcode() {
|
||||
// result instanceof Opcode::VarArgsStart
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * The IR translation of a `BuiltInVarArgsEnd` expression.
|
||||
// */
|
||||
//class TranslatedVarArgsEnd extends TranslatedBuiltInOperation {
|
||||
// override BuiltInVarArgsEnd expr;
|
||||
//
|
||||
// override final Opcode getOpcode() {
|
||||
// result instanceof Opcode::VarArgsEnd
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * The IR translation of a `BuiltInVarArg` expression.
|
||||
// */
|
||||
//class TranslatedVarArg extends TranslatedBuiltInOperation {
|
||||
// override BuiltInVarArg expr;
|
||||
//
|
||||
// override final Opcode getOpcode() {
|
||||
// result instanceof Opcode::VarArg
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * The IR translation of a `BuiltInVarArgCopy` expression.
|
||||
// */
|
||||
//class TranslatedVarArgCopy extends TranslatedBuiltInOperation {
|
||||
// override BuiltInVarArgCopy expr;
|
||||
//
|
||||
// override final Opcode getOpcode() {
|
||||
// result instanceof Opcode::VarArgCopy
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * The IR translation of a `new` or `new[]` expression.
|
||||
// */
|
||||
//abstract class TranslatedNewExpr extends TranslatedNonConstantExpr,
|
||||
// InitializationContext {
|
||||
// override ObjectCreation expr;
|
||||
//
|
||||
// override final TranslatedElement getChild(int id) {
|
||||
// id = 0 and result = getAllocatorCall() or
|
||||
// id = 1 and result = getInitialization()
|
||||
// }
|
||||
//
|
||||
// final TranslatedInitialization getInitialization() {
|
||||
// result = getTranslatedInitialization(expr.getInitializer())
|
||||
// }
|
||||
//
|
||||
// override final predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
// Type resultType, boolean isLValue) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getFirstInstruction() {
|
||||
// result = getAllocatorCall().getFirstInstruction()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getResult() {
|
||||
// result = getInstruction(OnlyInstructionTag())
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
// EdgeKind kind) {
|
||||
// kind instanceof GotoEdge and
|
||||
// tag = OnlyInstructionTag() and
|
||||
// if exists(getInitialization()) then
|
||||
// result = getInitialization().getFirstInstruction()
|
||||
// else
|
||||
// result = getParent().getChildSuccessor(this)
|
||||
// }
|
||||
//
|
||||
// override final Type getTargetType() {
|
||||
// result = expr.getType()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// child = getAllocatorCall() and result = getInstruction(OnlyInstructionTag()) or
|
||||
// child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionOperand(InstructionTag tag,
|
||||
// OperandTag operandTag) {
|
||||
// tag = OnlyInstructionTag() and
|
||||
// operandTag instanceof UnaryOperandTag and
|
||||
// result = getAllocatorCall().getResult()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getTargetAddress() {
|
||||
// result = getInstruction(OnlyInstructionTag())
|
||||
// }
|
||||
//
|
||||
// private TranslatedAllocatorCall getAllocatorCall() {
|
||||
// result = getTranslatedAllocatorCall(expr)
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
///**
|
||||
// * The IR translation of a `ConditionDeclExpr`, which represents the value of the declared variable
|
||||
// * after conversion to `bool` in code such as:
|
||||
// * ```
|
||||
// * if (int* p = &x) {
|
||||
// * }
|
||||
// * ```
|
||||
// */
|
||||
// TODO: DOESNT EXIST IN C#
|
||||
//class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr {
|
||||
// override ConditionDeclExpr expr;
|
||||
//
|
||||
// override final Instruction getFirstInstruction() {
|
||||
// result = getDecl().getFirstInstruction()
|
||||
// }
|
||||
//
|
||||
// override final TranslatedElement getChild(int id) {
|
||||
// id = 0 and result = getDecl() or
|
||||
// id = 1 and result = getConditionExpr()
|
||||
// }
|
||||
//
|
||||
// override Instruction getResult() {
|
||||
// result = getConditionExpr().getResult()
|
||||
// }
|
||||
//
|
||||
// override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// (
|
||||
// child = getDecl() and
|
||||
// result = getConditionExpr().getFirstInstruction()
|
||||
// ) or
|
||||
// child = getConditionExpr() and result = getParent().getChildSuccessor(this)
|
||||
// }
|
||||
//
|
||||
// override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType,
|
||||
// boolean ) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// private TranslatedConditionDecl getDecl() {
|
||||
// result = getTranslatedConditionDecl(expr)
|
||||
// }
|
||||
//
|
||||
// private TranslatedExpr getConditionExpr() {
|
||||
// result = getTranslatedExpr(expr.getVariableAccess().getFullyConverted())
|
||||
// }
|
||||
//}
|
||||
|
||||
/**
|
||||
* The IR translation of a lambda expression. This initializes a temporary variable whose type is that of the lambda,
|
||||
* using the initializer list that represents the captures of the lambda.
|
||||
|
||||
@@ -46,18 +46,15 @@ class TranslatedFunction extends TranslatedElement,
|
||||
}
|
||||
|
||||
override final TranslatedElement getChild(int id) {
|
||||
id = -3 and result = getConstructorInitList() or
|
||||
id = -2 and result = getBody() or
|
||||
id = -1 and result = getDestructorDestructionList() or
|
||||
id = -2 and result = getConstructorInitializer() or
|
||||
id = -1 and result = getBody() or
|
||||
id >= 0 and result = getParameter(id)
|
||||
}
|
||||
|
||||
private final TranslatedConstructorInitList getConstructorInitList() {
|
||||
result = getTranslatedConstructorInitList(callable)
|
||||
}
|
||||
|
||||
private final TranslatedDestructorDestructionList getDestructorDestructionList() {
|
||||
result = getTranslatedDestructorDestructionList(callable)
|
||||
private final TranslatedConstructorInitializer getConstructorInitializer() {
|
||||
exists(ConstructorInitializer ci |
|
||||
ci = callable.getAChild() and
|
||||
result = getTranslatedConstructorInitializer(ci))
|
||||
}
|
||||
|
||||
private final TranslatedStmt getBody() {
|
||||
@@ -97,7 +94,10 @@ class TranslatedFunction extends TranslatedElement,
|
||||
if exists(getParameter(0)) then
|
||||
result = getParameter(0).getFirstInstruction()
|
||||
else
|
||||
result = getConstructorInitList().getFirstInstruction()
|
||||
if (exists(getConstructorInitializer())) then
|
||||
result = getConstructorInitializer().getFirstInstruction()
|
||||
else
|
||||
result = getBody().getFirstInstruction()
|
||||
) or
|
||||
(
|
||||
tag = ReturnValueAddressTag() and
|
||||
@@ -124,22 +124,18 @@ class TranslatedFunction extends TranslatedElement,
|
||||
if exists(callable.getParameter(paramIndex + 1)) then
|
||||
result = getParameter(paramIndex + 1).getFirstInstruction()
|
||||
else
|
||||
result = getConstructorInitList().getFirstInstruction()
|
||||
if (exists(getConstructorInitializer())) then
|
||||
result = getConstructorInitializer().getFirstInstruction()
|
||||
else
|
||||
result = getBody().getFirstInstruction()
|
||||
) or
|
||||
(
|
||||
child = getConstructorInitList() and
|
||||
child = getConstructorInitializer() and
|
||||
result = getBody().getFirstInstruction()
|
||||
) or
|
||||
(
|
||||
child = getBody() and
|
||||
result = getReturnSuccessorInstruction()
|
||||
) or
|
||||
(
|
||||
child = getDestructorDestructionList() and
|
||||
if getReturnType() instanceof VoidType then
|
||||
result = getInstruction(ReturnTag())
|
||||
else
|
||||
result = getInstruction(ReturnValueAddressTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -361,8 +357,7 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
|
||||
}
|
||||
|
||||
override final Callable getFunction() {
|
||||
result = param.getCallable() // or
|
||||
// result = param.getCatchBlock().getEnclosingFunction()
|
||||
result = param.getCallable()
|
||||
}
|
||||
|
||||
override final Instruction getFirstInstruction() {
|
||||
@@ -427,149 +422,3 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private TranslatedConstructorInitList
|
||||
getTranslatedConstructorInitList(Callable callable) {
|
||||
result.getAST() = callable
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of a constructor initializer list. To simplify
|
||||
* the implementation of `TranslatedFunction`, a `TranslatedConstructorInitList`
|
||||
* exists for every function, not just for constructors. Of course, only the
|
||||
* instances for constructors can actually contain initializers.
|
||||
*/
|
||||
class TranslatedConstructorInitList extends TranslatedElement,
|
||||
InitializationContext, TTranslatedConstructorInitList {
|
||||
Callable callable;
|
||||
|
||||
TranslatedConstructorInitList() {
|
||||
this = TTranslatedConstructorInitList(callable)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "ctor init: " + callable.toString()
|
||||
}
|
||||
|
||||
override Language::AST getAST() {
|
||||
result = callable
|
||||
}
|
||||
|
||||
// TODO: Is this enough?
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = getTranslatedExpr(callable).getChild(id)
|
||||
// exists(MemberInitializer init |
|
||||
// init = callable.(Constructor).getInitializer().getRawArgument(id) and
|
||||
// result = getTranslatedConstructorFieldInitialization(init)
|
||||
// ) // or
|
||||
// exists(ConstructorBaseInit baseInit |
|
||||
// baseInit = callable.(Constructor).getInitializer().getRawArgument(id) and
|
||||
// result = getTranslatedConstructorBaseInit(baseInit)
|
||||
// )
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getChild(0)) then
|
||||
result = getChild(0).getFirstInstruction()
|
||||
else
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Callable getFunction() {
|
||||
result = callable
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id |
|
||||
child = getChild(id) and
|
||||
if exists(getChild(id + 1)) then
|
||||
result = getChild(id + 1).getFirstInstruction()
|
||||
else
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = getTranslatedFunction(callable).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
override Type getTargetType() {
|
||||
result = getTranslatedFunction(callable).getThisType()
|
||||
}
|
||||
}
|
||||
|
||||
private TranslatedDestructorDestructionList
|
||||
getTranslatedDestructorDestructionList(Callable callable) {
|
||||
result.getAST() = callable
|
||||
}
|
||||
|
||||
// TODO: Should not exist in C#, keep for now (the fix for getReturnSuccessorInstruction replaces it)
|
||||
/**
|
||||
* Represents the IR translation of a destructor's implicit calls to destructors
|
||||
* for fields and base classes. To simplify the implementation of `TranslatedFunction`,
|
||||
* a `TranslatedDestructorDestructionList` exists for every function, not just for
|
||||
* destructors. Of course, only the instances for destructors can actually contain
|
||||
* destructions.
|
||||
*/
|
||||
class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
TTranslatedDestructorDestructionList {
|
||||
Callable callable;
|
||||
|
||||
TranslatedDestructorDestructionList() {
|
||||
this = TTranslatedDestructorDestructionList(callable)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "dtor destruction: " + callable.toString()
|
||||
}
|
||||
|
||||
override Language::AST getAST() {
|
||||
result = callable
|
||||
}
|
||||
|
||||
// TODO: Is this enough?
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = getTranslatedExpr(callable).getChild(id)
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getChild(0)) then
|
||||
result = getChild(0).getFirstInstruction()
|
||||
else
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
|
||||
Type resultType, boolean isLValue) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Callable getFunction() {
|
||||
result = callable
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag,
|
||||
EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id |
|
||||
child = getChild(id) and
|
||||
if exists(getChild(id + 1)) then
|
||||
result = getChild(id + 1).getFirstInstruction()
|
||||
else
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +220,17 @@ class TranslatedObjectInitialization extends TranslatedInitialization,
|
||||
resultType = expr.getType() and
|
||||
isLValue = false
|
||||
)
|
||||
or
|
||||
(
|
||||
needsConversion() and
|
||||
tag = AssignmentConvertRightTag() and
|
||||
// For now only use `Opcode::Convert` to
|
||||
// crudely represent conversions. Could
|
||||
// be useful to represent the whole chain of conversions
|
||||
opcode instanceof Opcode::Convert and
|
||||
resultType = getContext().getTargetType() and
|
||||
isLValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override final Instruction getFirstInstruction() {
|
||||
@@ -238,6 +249,11 @@ class TranslatedObjectInitialization extends TranslatedInitialization,
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
or
|
||||
(
|
||||
tag = AssignmentConvertRightTag() and
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -247,21 +263,40 @@ class TranslatedObjectInitialization extends TranslatedInitialization,
|
||||
if (exists(getInitializerExpr())) then
|
||||
result = getInitializerExpr().getFirstInstruction()
|
||||
else
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
if needsConversion() then
|
||||
result = getInstruction(AssignmentConvertRightTag())
|
||||
else
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
) or
|
||||
(
|
||||
child = getInitializerExpr() and
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
if (needsConversion()) then
|
||||
result = getInstruction(AssignmentConvertRightTag())
|
||||
else
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
) or
|
||||
(
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
if (needsConversion()) then
|
||||
result = getInstruction(AssignmentConvertRightTag())
|
||||
else
|
||||
result = getInstruction(NewObjTag())
|
||||
)
|
||||
)
|
||||
) or
|
||||
(
|
||||
tag = AssignmentConvertRightTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getInstruction(NewObjTag())
|
||||
)
|
||||
}
|
||||
@@ -278,6 +313,10 @@ class TranslatedObjectInitialization extends TranslatedInitialization,
|
||||
// The newly allocated object will be the target of the constructor call
|
||||
result = getInstruction(NewObjTag())
|
||||
}
|
||||
|
||||
private predicate needsConversion() {
|
||||
expr.getType() != getContext().getTargetType()
|
||||
}
|
||||
}
|
||||
|
||||
///**
|
||||
@@ -652,7 +691,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext {
|
||||
// TODO: Possibly refactor into something simpler
|
||||
abstract class TranslatedConstructorCallFromConstructor extends TranslatedElement, StructorCallContext {
|
||||
Call call;
|
||||
|
||||
override final Language::AST getAST() {
|
||||
@@ -660,8 +700,7 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
}
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = getStructorCall()
|
||||
id = 0 and result = getStructorCall()
|
||||
}
|
||||
|
||||
final override Callable getFunction() { result = call.getEnclosingCallable() }
|
||||
@@ -674,37 +713,66 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of a call to a base class constructor or
|
||||
* destructor from within a derived class constructor or destructor.
|
||||
*/
|
||||
abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor {
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override predicate hasInstruction(
|
||||
TranslatedConstructorInitializer getTranslatedConstructorInitializer(ConstructorInitializer ci) {
|
||||
result.getAST() = ci
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of a call to a base class constructor
|
||||
* or another constructor in same class from a class constructor.
|
||||
*/
|
||||
class TranslatedConstructorInitializer extends TranslatedConstructorCallFromConstructor,
|
||||
TTranslatedConstructorInitializer {
|
||||
TranslatedConstructorInitializer() {
|
||||
this = TTranslatedConstructorInitializer(call)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "constuructor init: " + call.toString()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if (needsConversion()) then
|
||||
result = getInstruction(OnlyInstructionTag())
|
||||
else
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(
|
||||
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
|
||||
) {
|
||||
needsConversion() and
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::ConvertToBase and
|
||||
resultType = call.getTarget().getDeclaringType() and
|
||||
isLValue = true
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getReceiver() {
|
||||
if (needsConversion()) then
|
||||
result = getInstruction(OnlyInstructionTag())
|
||||
else
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override predicate getInstructionInheritance(
|
||||
predicate needsConversion() {
|
||||
call.getTarget().getDeclaringType() != getFunction().getDeclaringType()
|
||||
}
|
||||
|
||||
override predicate getInstructionInheritance(
|
||||
InstructionTag tag, Class baseClass, Class derivedClass
|
||||
) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -712,72 +780,3 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
derivedClass = getFunction().getDeclaringType()
|
||||
}
|
||||
}
|
||||
//abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor,
|
||||
// TTranslatedConstructorBaseInit {
|
||||
// TranslatedConstructorCallFromConstructor() {
|
||||
// this = TTranslatedConstructorBaseInit(call)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) {
|
||||
// result.getAST() = init
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Represents the IR translation of a delegating constructor call from within a constructor.
|
||||
// */
|
||||
//class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromConstructor {
|
||||
// override ConstructorDelegationInit call;
|
||||
//
|
||||
// override final string toString() {
|
||||
// result = "delegation construct: " + call.toString()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getFirstInstruction() {
|
||||
// result = getStructorCall().getFirstInstruction()
|
||||
// }
|
||||
//
|
||||
// override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
// none()
|
||||
// }
|
||||
//
|
||||
// override final Instruction getReceiver() {
|
||||
// result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Represents the IR translation of a call to a base class constructor from within a
|
||||
// * derived class constructor
|
||||
// */
|
||||
//class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, TranslatedBaseStructorCall {
|
||||
// TranslatedConstructorBaseInit() {
|
||||
// not call instanceof ConstructorDelegationInit
|
||||
// }
|
||||
//
|
||||
// override final string toString() {
|
||||
// result = "construct base: " + call.toString()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) {
|
||||
// result.getAST() = destruction
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Represents the IR translation of a call to a base class destructor from within a
|
||||
// * derived class destructor.
|
||||
// */
|
||||
//class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, TTranslatedDestructorBaseDestruction {
|
||||
// TranslatedDestructorBaseDestruction() {
|
||||
// this = TTranslatedDestructorBaseDestruction(call)
|
||||
// }
|
||||
//
|
||||
// override final string toString() {
|
||||
// result = "destroy base: " + call.toString()
|
||||
// }
|
||||
//}
|
||||
|
||||
35
csharp/ql/test/library-tests/ir/ir/constructor_init.cs
Normal file
35
csharp/ql/test/library-tests/ir/ir/constructor_init.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
public class BaseClass
|
||||
{
|
||||
int num;
|
||||
|
||||
public BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
public BaseClass(int i)
|
||||
{
|
||||
num = i;
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass : BaseClass
|
||||
{
|
||||
public DerivedClass() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public DerivedClass(int i) : base(i)
|
||||
{
|
||||
}
|
||||
|
||||
public DerivedClass(int i, int j): this(i)
|
||||
{
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
DerivedClass obj1= new DerivedClass();
|
||||
DerivedClass obj2 = new DerivedClass(1);
|
||||
DerivedClass obj3 = new DerivedClass(1, 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
public class A
|
||||
{
|
||||
public virtual int function()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class B : A
|
||||
{
|
||||
}
|
||||
|
||||
class C : B
|
||||
{
|
||||
public override int function()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
B objB = new B();
|
||||
objB.function();
|
||||
|
||||
// Check conversion works
|
||||
A objA;
|
||||
objA = objB;
|
||||
objA.function();
|
||||
|
||||
A objC = new C();
|
||||
objC.function();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -135,6 +135,120 @@ array.cs:
|
||||
# 9| v0_85(Void) = UnmodeledUse : mu*
|
||||
# 9| v0_86(Void) = ExitFunction :
|
||||
|
||||
constructor_init.cs:
|
||||
# 5| BaseClass
|
||||
# 5| Block 0
|
||||
# 5| v0_0(Void) = EnterFunction :
|
||||
# 5| mu0_1(null) = AliasedDefinition :
|
||||
# 5| mu0_2(null) = UnmodeledDefinition :
|
||||
# 5| r0_3(glval<BaseClass>) = InitializeThis :
|
||||
# 6| v0_4(Void) = NoOp :
|
||||
# 5| v0_5(Void) = ReturnVoid :
|
||||
# 5| v0_6(Void) = UnmodeledUse : mu*
|
||||
# 5| v0_7(Void) = ExitFunction :
|
||||
|
||||
# 9| BaseClass
|
||||
# 9| Block 0
|
||||
# 9| v0_0(Void) = EnterFunction :
|
||||
# 9| mu0_1(null) = AliasedDefinition :
|
||||
# 9| mu0_2(null) = UnmodeledDefinition :
|
||||
# 9| r0_3(glval<BaseClass>) = InitializeThis :
|
||||
# 9| r0_4(glval<Int32>) = VariableAddress[i] :
|
||||
# 9| mu0_5(Int32) = InitializeParameter[i] : &:r0_4
|
||||
# 11| r0_6(glval<Int32>) = VariableAddress[i] :
|
||||
# 11| r0_7(Int32) = Load : &:r0_6, ~mu0_2
|
||||
# 11| r0_8(BaseClass) = CopyValue : r0_3
|
||||
# 11| r0_9(glval<Int32>) = FieldAddress[BaseClass.num] : r0_8
|
||||
# 11| mu0_10(Int32) = Store : &:r0_9, r0_7
|
||||
# 9| v0_11(Void) = ReturnVoid :
|
||||
# 9| v0_12(Void) = UnmodeledUse : mu*
|
||||
# 9| v0_13(Void) = ExitFunction :
|
||||
|
||||
# 17| DerivedClass
|
||||
# 17| Block 0
|
||||
# 17| v0_0(Void) = EnterFunction :
|
||||
# 17| mu0_1(null) = AliasedDefinition :
|
||||
# 17| mu0_2(null) = UnmodeledDefinition :
|
||||
# 17| r0_3(glval<DerivedClass>) = InitializeThis :
|
||||
# 17| r0_4(glval<BaseClass>) = ConvertToBase[DerivedClass : BaseClass] : r0_3
|
||||
# 17| r0_5(glval<BaseClass>) = FunctionAddress[BaseClass.BaseClass()] :
|
||||
# 17| r0_6(BaseClass) = Call : func:r0_5, this:r0_4
|
||||
# 17| mu0_7(null) = ^CallSideEffect : ~mu0_2
|
||||
# 18| v0_8(Void) = NoOp :
|
||||
# 17| v0_9(Void) = ReturnVoid :
|
||||
# 17| v0_10(Void) = UnmodeledUse : mu*
|
||||
# 17| v0_11(Void) = ExitFunction :
|
||||
|
||||
# 21| DerivedClass
|
||||
# 21| Block 0
|
||||
# 21| v0_0(Void) = EnterFunction :
|
||||
# 21| mu0_1(null) = AliasedDefinition :
|
||||
# 21| mu0_2(null) = UnmodeledDefinition :
|
||||
# 21| r0_3(glval<DerivedClass>) = InitializeThis :
|
||||
# 21| r0_4(glval<Int32>) = VariableAddress[i] :
|
||||
# 21| mu0_5(Int32) = InitializeParameter[i] : &:r0_4
|
||||
# 21| r0_6(glval<BaseClass>) = ConvertToBase[DerivedClass : BaseClass] : r0_3
|
||||
# 21| r0_7(glval<BaseClass>) = FunctionAddress[BaseClass.BaseClass(int)] :
|
||||
# 21| r0_8(glval<Int32>) = VariableAddress[i] :
|
||||
# 21| r0_9(Int32) = Load : &:r0_8, ~mu0_2
|
||||
# 21| r0_10(BaseClass) = Call : func:r0_7, this:r0_6, 0:r0_9
|
||||
# 21| mu0_11(null) = ^CallSideEffect : ~mu0_2
|
||||
# 22| v0_12(Void) = NoOp :
|
||||
# 21| v0_13(Void) = ReturnVoid :
|
||||
# 21| v0_14(Void) = UnmodeledUse : mu*
|
||||
# 21| v0_15(Void) = ExitFunction :
|
||||
|
||||
# 25| DerivedClass
|
||||
# 25| Block 0
|
||||
# 25| v0_0(Void) = EnterFunction :
|
||||
# 25| mu0_1(null) = AliasedDefinition :
|
||||
# 25| mu0_2(null) = UnmodeledDefinition :
|
||||
# 25| r0_3(glval<DerivedClass>) = InitializeThis :
|
||||
# 25| r0_4(glval<Int32>) = VariableAddress[i] :
|
||||
# 25| mu0_5(Int32) = InitializeParameter[i] : &:r0_4
|
||||
# 25| r0_6(glval<Int32>) = VariableAddress[j] :
|
||||
# 25| mu0_7(Int32) = InitializeParameter[j] : &:r0_6
|
||||
# 25| r0_8(glval<DerivedClass>) = FunctionAddress[DerivedClass.DerivedClass(int)] :
|
||||
# 25| r0_9(glval<Int32>) = VariableAddress[i] :
|
||||
# 25| r0_10(Int32) = Load : &:r0_9, ~mu0_2
|
||||
# 25| r0_11(DerivedClass) = Call : func:r0_8, this:r0_3, 0:r0_10
|
||||
# 25| mu0_12(null) = ^CallSideEffect : ~mu0_2
|
||||
# 26| v0_13(Void) = NoOp :
|
||||
# 25| v0_14(Void) = ReturnVoid :
|
||||
# 25| v0_15(Void) = UnmodeledUse : mu*
|
||||
# 25| v0_16(Void) = ExitFunction :
|
||||
|
||||
# 29| Main
|
||||
# 29| Block 0
|
||||
# 29| v0_0(Void) = EnterFunction :
|
||||
# 29| mu0_1(null) = AliasedDefinition :
|
||||
# 29| mu0_2(null) = UnmodeledDefinition :
|
||||
# 29| r0_3(glval<DerivedClass>) = InitializeThis :
|
||||
# 31| r0_4(glval<DerivedClass>) = VariableAddress[obj1] :
|
||||
# 31| r0_5(DerivedClass) = NewObj :
|
||||
# 31| r0_6(glval<DerivedClass>) = FunctionAddress[DerivedClass.DerivedClass()] :
|
||||
# 31| r0_7(DerivedClass) = Call : func:r0_6, this:r0_5
|
||||
# 31| mu0_8(null) = ^CallSideEffect : ~mu0_2
|
||||
# 31| mu0_9(DerivedClass) = Store : &:r0_4, r0_5
|
||||
# 32| r0_10(glval<DerivedClass>) = VariableAddress[obj2] :
|
||||
# 32| r0_11(DerivedClass) = NewObj :
|
||||
# 32| r0_12(glval<DerivedClass>) = FunctionAddress[DerivedClass.DerivedClass(int)] :
|
||||
# 32| r0_13(Int32) = Constant[1] :
|
||||
# 32| r0_14(DerivedClass) = Call : func:r0_12, this:r0_11, 0:r0_13
|
||||
# 32| mu0_15(null) = ^CallSideEffect : ~mu0_2
|
||||
# 32| mu0_16(DerivedClass) = Store : &:r0_10, r0_11
|
||||
# 33| r0_17(glval<DerivedClass>) = VariableAddress[obj3] :
|
||||
# 33| r0_18(DerivedClass) = NewObj :
|
||||
# 33| r0_19(glval<DerivedClass>) = FunctionAddress[DerivedClass.DerivedClass(int, int)] :
|
||||
# 33| r0_20(Int32) = Constant[1] :
|
||||
# 33| r0_21(Int32) = Constant[2] :
|
||||
# 33| r0_22(DerivedClass) = Call : func:r0_19, this:r0_18, 0:r0_20, 1:r0_21
|
||||
# 33| mu0_23(null) = ^CallSideEffect : ~mu0_2
|
||||
# 33| mu0_24(DerivedClass) = Store : &:r0_17, r0_18
|
||||
# 29| v0_25(Void) = ReturnVoid :
|
||||
# 29| v0_26(Void) = UnmodeledUse : mu*
|
||||
# 29| v0_27(Void) = ExitFunction :
|
||||
|
||||
crement.cs:
|
||||
# 2| Main
|
||||
# 2| Block 0
|
||||
@@ -218,6 +332,76 @@ func_with_param_call.cs:
|
||||
# 8| v0_13(Void) = UnmodeledUse : mu*
|
||||
# 8| v0_14(Void) = ExitFunction :
|
||||
|
||||
inheritance_polymorphism.cs:
|
||||
# 3| function
|
||||
# 3| Block 0
|
||||
# 3| v0_0(Void) = EnterFunction :
|
||||
# 3| mu0_1(null) = AliasedDefinition :
|
||||
# 3| mu0_2(null) = UnmodeledDefinition :
|
||||
# 3| r0_3(glval<A>) = InitializeThis :
|
||||
# 5| r0_4(glval<Int32>) = VariableAddress[#return] :
|
||||
# 5| r0_5(Int32) = Constant[0] :
|
||||
# 5| mu0_6(Int32) = Store : &:r0_4, r0_5
|
||||
# 3| r0_7(glval<Int32>) = VariableAddress[#return] :
|
||||
# 3| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2
|
||||
# 3| v0_9(Void) = UnmodeledUse : mu*
|
||||
# 3| v0_10(Void) = ExitFunction :
|
||||
|
||||
# 15| function
|
||||
# 15| Block 0
|
||||
# 15| v0_0(Void) = EnterFunction :
|
||||
# 15| mu0_1(null) = AliasedDefinition :
|
||||
# 15| mu0_2(null) = UnmodeledDefinition :
|
||||
# 15| r0_3(glval<C>) = InitializeThis :
|
||||
# 17| r0_4(glval<Int32>) = VariableAddress[#return] :
|
||||
# 17| r0_5(Int32) = Constant[1] :
|
||||
# 17| mu0_6(Int32) = Store : &:r0_4, r0_5
|
||||
# 15| r0_7(glval<Int32>) = VariableAddress[#return] :
|
||||
# 15| v0_8(Void) = ReturnValue : &:r0_7, ~mu0_2
|
||||
# 15| v0_9(Void) = UnmodeledUse : mu*
|
||||
# 15| v0_10(Void) = ExitFunction :
|
||||
|
||||
# 23| Main
|
||||
# 23| Block 0
|
||||
# 23| v0_0(Void) = EnterFunction :
|
||||
# 23| mu0_1(null) = AliasedDefinition :
|
||||
# 23| mu0_2(null) = UnmodeledDefinition :
|
||||
# 23| r0_3(glval<Program>) = InitializeThis :
|
||||
# 25| r0_4(glval<B>) = VariableAddress[objB] :
|
||||
# 25| r0_5(B) = NewObj :
|
||||
# 25| r0_6(glval<B>) = FunctionAddress[B.B()] :
|
||||
# 25| r0_7(B) = Call : func:r0_6, this:r0_5
|
||||
# 25| mu0_8(null) = ^CallSideEffect : ~mu0_2
|
||||
# 25| mu0_9(B) = Store : &:r0_4, r0_5
|
||||
# 26| r0_10(glval<B>) = VariableAddress[objB] :
|
||||
# 26| r0_11(glval<Int32>) = FunctionAddress[A.function()] :
|
||||
# 26| r0_12(Int32) = Call : func:r0_11, this:r0_10
|
||||
# 26| mu0_13(null) = ^CallSideEffect : ~mu0_2
|
||||
# 29| r0_14(glval<A>) = VariableAddress[objA] :
|
||||
# 29| mu0_15(A) = Uninitialized[objA] : &:r0_14
|
||||
# 30| r0_16(glval<B>) = VariableAddress[objB] :
|
||||
# 30| r0_17(A) = Convert : r0_16
|
||||
# 30| r0_18(glval<A>) = VariableAddress[objA] :
|
||||
# 30| mu0_19(A) = Store : &:r0_18, r0_17
|
||||
# 31| r0_20(glval<A>) = VariableAddress[objA] :
|
||||
# 31| r0_21(glval<Int32>) = FunctionAddress[A.function()] :
|
||||
# 31| r0_22(Int32) = Call : func:r0_21, this:r0_20
|
||||
# 31| mu0_23(null) = ^CallSideEffect : ~mu0_2
|
||||
# 33| r0_24(glval<A>) = VariableAddress[objC] :
|
||||
# 33| r0_25(C) = NewObj :
|
||||
# 33| r0_26(glval<C>) = FunctionAddress[C.C()] :
|
||||
# 33| r0_27(C) = Call : func:r0_26, this:r0_25
|
||||
# 33| mu0_28(null) = ^CallSideEffect : ~mu0_2
|
||||
# 33| r0_29(A) = Convert : r0_25
|
||||
# 33| mu0_30(C) = Store : &:r0_24, r0_29
|
||||
# 34| r0_31(glval<A>) = VariableAddress[objC] :
|
||||
# 34| r0_32(glval<Int32>) = FunctionAddress[A.function()] :
|
||||
# 34| r0_33(Int32) = Call : func:r0_32, this:r0_31
|
||||
# 34| mu0_34(null) = ^CallSideEffect : ~mu0_2
|
||||
# 23| v0_35(Void) = ReturnVoid :
|
||||
# 23| v0_36(Void) = UnmodeledUse : mu*
|
||||
# 23| v0_37(Void) = ExitFunction :
|
||||
|
||||
obj_creation.cs:
|
||||
# 5| MyClass
|
||||
# 5| Block 0
|
||||
|
||||
Reference in New Issue
Block a user