Skip to content

Commit f5acc51

Browse files
authored
Merge pull request github#5909 from tamasvajk/fix/foreach-ir-temp-var
C#: Fix type of temp foreach variable in IR
2 parents 131c08e + 6853f6a commit f5acc51

File tree

5 files changed

+59
-38
lines changed

5 files changed

+59
-38
lines changed

csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Common.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,21 @@ abstract class TranslatedCompilerGeneratedVariableAccess extends TranslatedCompi
182182

183183
override Instruction getChildSuccessor(TranslatedElement child) { none() }
184184

185+
/**
186+
* Returns the type of the accessed variable. Can be overriden when the return
187+
* type is different than the type of the underlying variable.
188+
*/
189+
Type getVariableType() { result = getResultType() }
190+
185191
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) {
186192
tag = AddressTag() and
187193
opcode instanceof Opcode::VariableAddress and
188-
resultType = getTypeForGLValue(getResultType())
194+
resultType = getTypeForGLValue(getVariableType())
189195
or
190196
needsLoad() and
191197
tag = LoadTag() and
192198
opcode instanceof Opcode::Load and
193-
resultType = getTypeForPRValue(getResultType())
199+
resultType = getTypeForPRValue(getVariableType())
194200
}
195201

196202
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {

csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,16 @@ private class TranslatedMoveNextEnumAcc extends TTranslatedCompilerGeneratedElem
359359

360360
override Type getResultType() { result instanceof BoolType }
361361

362+
override Type getVariableType() {
363+
exists(TranslatedForeachGetEnumerator ge |
364+
ge.getAST() = generatedBy and
365+
result = ge.getCallResultType()
366+
)
367+
}
368+
362369
override predicate hasTempVariable(TempVariableTag tag, CSharpType type) {
363370
tag = ForeachEnumTempVar() and
364-
type = getTypeForPRValue(getResultType())
371+
type = getTypeForPRValue(getVariableType())
365372
}
366373

367374
override IRVariable getInstructionVariable(InstructionTag tag) {
@@ -384,9 +391,16 @@ private class TranslatedForeachCurrentEnumAcc extends TTranslatedCompilerGenerat
384391

385392
override Type getResultType() { result instanceof BoolType }
386393

394+
override Type getVariableType() {
395+
exists(TranslatedForeachGetEnumerator ge |
396+
ge.getAST() = generatedBy and
397+
result = ge.getCallResultType()
398+
)
399+
}
400+
387401
override predicate hasTempVariable(TempVariableTag tag, CSharpType type) {
388402
tag = ForeachEnumTempVar() and
389-
type = getTypeForPRValue(getResultType())
403+
type = getTypeForPRValue(getVariableType())
390404
}
391405

392406
override IRVariable getInstructionVariable(InstructionTag tag) {
@@ -409,9 +423,16 @@ private class TranslatedForeachDisposeEnumAcc extends TTranslatedCompilerGenerat
409423

410424
override Type getResultType() { result instanceof BoolType }
411425

426+
override Type getVariableType() {
427+
exists(TranslatedForeachGetEnumerator ge |
428+
ge.getAST() = generatedBy and
429+
result = ge.getCallResultType()
430+
)
431+
}
432+
412433
override predicate hasTempVariable(TempVariableTag tag, CSharpType type) {
413434
tag = ForeachEnumTempVar() and
414-
type = getTypeForPRValue(getResultType())
435+
type = getTypeForPRValue(getVariableType())
415436
}
416437

417438
override IRVariable getInstructionVariable(InstructionTag tag) {

csharp/ql/test/experimental/ir/ir/raw_ir.expected

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -613,48 +613,48 @@ foreach.cs:
613613
# 5| r5_28(glval<Int32>) = PointerAdd[4] : r5_1, r5_27
614614
# 5| r5_29(Int32) = Constant[7] :
615615
# 5| mu5_30(Int32) = Store[?] : &:r5_28, r5_29
616-
# 7| r7_1(glval<Boolean>) = VariableAddress[#temp7:9] :
616+
# 7| r7_1(glval<IEnumerator>) = VariableAddress[#temp7:9] :
617617
# 7| r7_2(glval<Int32[]>) = VariableAddress[a_array] :
618618
# 7| r7_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
619619
# 7| r7_4(<funcaddr>) = FunctionAddress[GetEnumerator] :
620620
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
621621
# 7| mu7_6(<unknown>) = ^CallSideEffect : ~m?
622-
# 7| mu7_7(Boolean) = Store[#temp7:9] : &:r7_1, r7_5
622+
# 7| mu7_7(IEnumerator) = Store[#temp7:9] : &:r7_1, r7_5
623623
#-----| Goto -> Block 1
624624

625625
# 7| Block 1
626-
# 7| r7_8(glval<Boolean>) = VariableAddress[#temp7:9] :
627-
# 7| r7_9(Boolean) = Load[#temp7:9] : &:r7_8, ~m?
628-
# 7| r7_10(<funcaddr>) = FunctionAddress[MoveNext] :
629-
# 7| r7_11(Boolean) = Call[MoveNext] : func:r7_10, this:r7_9
630-
# 7| mu7_12(<unknown>) = ^CallSideEffect : ~m?
631-
# 7| v7_13(Void) = ConditionalBranch : r7_11
626+
# 7| r7_8(glval<IEnumerator>) = VariableAddress[#temp7:9] :
627+
# 7| r7_9(IEnumerator) = Load[#temp7:9] : &:r7_8, ~m?
628+
# 7| r7_10(<funcaddr>) = FunctionAddress[MoveNext] :
629+
# 7| r7_11(Boolean) = Call[MoveNext] : func:r7_10, this:r7_9
630+
# 7| mu7_12(<unknown>) = ^CallSideEffect : ~m?
631+
# 7| v7_13(Void) = ConditionalBranch : r7_11
632632
#-----| False -> Block 3
633633
#-----| True -> Block 2
634634

635635
# 7| Block 2
636-
# 7| r7_14(glval<Int32>) = VariableAddress[items] :
637-
# 7| r7_15(glval<Boolean>) = VariableAddress[#temp7:9] :
638-
# 7| r7_16(Boolean) = Load[#temp7:9] : &:r7_15, ~m?
639-
# 7| r7_17(<funcaddr>) = FunctionAddress[get_Current] :
640-
# 7| r7_18(Int32) = Call[get_Current] : func:r7_17, this:r7_16
641-
# 7| mu7_19(<unknown>) = ^CallSideEffect : ~m?
642-
# 7| mu7_20(Int32) = Store[items] : &:r7_14, r7_18
643-
# 9| r9_1(glval<Int32>) = VariableAddress[x] :
644-
# 9| r9_2(glval<Int32>) = VariableAddress[items] :
645-
# 9| r9_3(Int32) = Load[items] : &:r9_2, ~m?
646-
# 9| mu9_4(Int32) = Store[x] : &:r9_1, r9_3
636+
# 7| r7_14(glval<Int32>) = VariableAddress[items] :
637+
# 7| r7_15(glval<IEnumerator>) = VariableAddress[#temp7:9] :
638+
# 7| r7_16(IEnumerator) = Load[#temp7:9] : &:r7_15, ~m?
639+
# 7| r7_17(<funcaddr>) = FunctionAddress[get_Current] :
640+
# 7| r7_18(Int32) = Call[get_Current] : func:r7_17, this:r7_16
641+
# 7| mu7_19(<unknown>) = ^CallSideEffect : ~m?
642+
# 7| mu7_20(Int32) = Store[items] : &:r7_14, r7_18
643+
# 9| r9_1(glval<Int32>) = VariableAddress[x] :
644+
# 9| r9_2(glval<Int32>) = VariableAddress[items] :
645+
# 9| r9_3(Int32) = Load[items] : &:r9_2, ~m?
646+
# 9| mu9_4(Int32) = Store[x] : &:r9_1, r9_3
647647
#-----| Goto (back edge) -> Block 1
648648

649649
# 7| Block 3
650-
# 7| r7_21(glval<Boolean>) = VariableAddress[#temp7:9] :
651-
# 7| r7_22(Boolean) = Load[#temp7:9] : &:r7_21, ~m?
652-
# 7| r7_23(<funcaddr>) = FunctionAddress[Dispose] :
653-
# 7| v7_24(Void) = Call[Dispose] : func:r7_23, this:r7_22
654-
# 7| mu7_25(<unknown>) = ^CallSideEffect : ~m?
655-
# 4| v4_3(Void) = ReturnVoid :
656-
# 4| v4_4(Void) = AliasedUse : ~m?
657-
# 4| v4_5(Void) = ExitFunction :
650+
# 7| r7_21(glval<IEnumerator>) = VariableAddress[#temp7:9] :
651+
# 7| r7_22(IEnumerator) = Load[#temp7:9] : &:r7_21, ~m?
652+
# 7| r7_23(<funcaddr>) = FunctionAddress[Dispose] :
653+
# 7| v7_24(Void) = Call[Dispose] : func:r7_23, this:r7_22
654+
# 7| mu7_25(<unknown>) = ^CallSideEffect : ~m?
655+
# 4| v4_3(Void) = ReturnVoid :
656+
# 4| v4_4(Void) = AliasedUse : ~m?
657+
# 4| v4_5(Void) = ExitFunction :
658658

659659
func_with_param_call.cs:
660660
# 5| System.Int32 test_call_with_param.f(System.Int32,System.Int32)

csharp/ql/test/experimental/ir/ir/raw_ir_consistency.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ fieldAddressOnNonPointer
2626
| inoutref.cs:19:13:19:17 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | inoutref.cs:16:17:16:17 | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) |
2727
| pointers.cs:35:17:35:24 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
2828
thisArgumentIsNonPointer
29-
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
30-
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
31-
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
3229
| inoutref.cs:32:22:32:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | inoutref.cs:29:17:29:20 | System.Void InOutRef.Main() | System.Void InOutRef.Main() |
3330
| pointers.cs:27:22:27:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
3431
missingCanonicalLanguageType

csharp/ql/test/experimental/ir/ir/unaliased_ssa_consistency.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ fieldAddressOnNonPointer
2626
| inoutref.cs:19:13:19:17 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | inoutref.cs:16:17:16:17 | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) | System.Void InOutRef.F(System.Int32,MyStruct,MyStruct,MyClass,MyClass) |
2727
| pointers.cs:35:17:35:24 | FieldAddress: access to field fld | FieldAddress instruction 'FieldAddress: access to field fld' has an object address operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
2828
thisArgumentIsNonPointer
29-
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
30-
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
31-
| foreach.cs:7:9:10:9 | Call: foreach (... ... in ...) ... | Call instruction 'Call: foreach (... ... in ...) ...' has a `this` argument operand that is not an address, in function '$@'. | foreach.cs:4:24:4:27 | System.Void ForEach.Main() | System.Void ForEach.Main() |
3229
| inoutref.cs:32:22:32:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | inoutref.cs:29:17:29:20 | System.Void InOutRef.Main() | System.Void InOutRef.Main() |
3330
| pointers.cs:27:22:27:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() |
3431
missingCanonicalLanguageType

0 commit comments

Comments
 (0)