Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 420abbf

Browse files
author
AndreiDiaconu1
committed
C# IR: Support for ContinueStmt
Added support for continue stmt. Minimal refactoring of the `TranslatedSpecificJump` classes. Added a new test file, `jumps.cs` and updated the expected output.
1 parent 10076a6 commit 420abbf

3 files changed

Lines changed: 216 additions & 13 deletions

File tree

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -731,17 +731,24 @@ abstract class TranslatedSpecificJump extends TranslatedStmt {
731731
isLValue = false
732732
}
733733

734-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
734+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
735+
tag = OnlyInstructionTag() and
736+
kind instanceof GotoEdge and
737+
result = getTargetInstruction()
738+
}
735739

736740
override Instruction getChildSuccessor(TranslatedElement child) { none() }
741+
742+
/**
743+
* The instruction that is the target of the jump.
744+
*/
745+
abstract Instruction getTargetInstruction();
737746
}
738747

739748
class TranslatedBreakStmt extends TranslatedSpecificJump {
740749
override BreakStmt stmt;
741750

742-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
743-
tag = OnlyInstructionTag() and
744-
kind instanceof GotoEdge and
751+
override Instruction getTargetInstruction() {
745752
result = this.getEnclosingLoopOrSwitchNextInstr(stmt)
746753
}
747754

@@ -753,22 +760,36 @@ class TranslatedBreakStmt extends TranslatedSpecificJump {
753760
}
754761
}
755762

763+
class TranslatedContinueStmt extends TranslatedSpecificJump {
764+
override ContinueStmt stmt;
765+
766+
override Instruction getTargetInstruction() {
767+
result = this.getEnclosingLoopTargetInstruction(stmt)
768+
}
769+
770+
private Instruction getEnclosingLoopTargetInstruction(Stmt crtStmt) {
771+
if crtStmt instanceof LoopStmt
772+
then
773+
if crtStmt instanceof ForStmt
774+
then
775+
result = getTranslatedStmt(crtStmt).(TranslatedForStmt).getUpdate(0).getFirstInstruction()
776+
else result = getTranslatedStmt(crtStmt).getFirstInstruction()
777+
else result = this.getEnclosingLoopTargetInstruction(crtStmt.getParent())
778+
}
779+
}
780+
756781
class TranslatedGotoLabelStmt extends TranslatedSpecificJump {
757782
override GotoLabelStmt stmt;
758783

759-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
760-
tag = OnlyInstructionTag() and
761-
kind instanceof GotoEdge and
784+
override Instruction getTargetInstruction() {
762785
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction()
763786
}
764787
}
765788

766789
class TranslatedGotoCaseStmt extends TranslatedSpecificJump {
767790
override GotoCaseStmt stmt;
768791

769-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
770-
tag = OnlyInstructionTag() and
771-
kind instanceof GotoEdge and
792+
override Instruction getTargetInstruction() {
772793
result = this.getCase(stmt, stmt.getExpr()).getFirstInstruction()
773794
}
774795

@@ -789,9 +810,7 @@ class TranslatedGotoCaseStmt extends TranslatedSpecificJump {
789810
class TranslatedGotoDefaultStmt extends TranslatedSpecificJump {
790811
override GotoDefaultStmt stmt;
791812

792-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
793-
tag = OnlyInstructionTag() and
794-
kind instanceof GotoEdge and
813+
override Instruction getTargetInstruction() {
795814
result = getDefaultCase(stmt).getFirstInstruction()
796815
}
797816

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
3+
class Jumps
4+
{
5+
public static void Main()
6+
{
7+
for (int i = 1; i <= 10; i++)
8+
{
9+
if (i == 3)
10+
continue;
11+
else if (i == 5)
12+
break;
13+
Console.WriteLine("BreakAndContinue");
14+
}
15+
16+
int a = 0;
17+
while (true)
18+
{
19+
a++;
20+
if (a == 5)
21+
continue;
22+
if (a == 10)
23+
break;
24+
}
25+
26+
for (int i = 1; i <= 10; i++)
27+
{
28+
if (i == 5)
29+
goto done;
30+
}
31+
done:
32+
Console.WriteLine("Done");
33+
}
34+
}

csharp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,156 @@ isexpr.cs:
603603
# 18| v6_0(Void) = NoOp :
604604
#-----| Goto -> Block 1
605605

606+
jumps.cs:
607+
# 5| System.Void Jumps.Main()
608+
# 5| Block 0
609+
# 5| v0_0(Void) = EnterFunction :
610+
# 5| mu0_1(null) = AliasedDefinition :
611+
# 5| mu0_2(null) = UnmodeledDefinition :
612+
# 7| r0_3(glval<Int32>) = VariableAddress[i] :
613+
# 7| r0_4(Int32) = Constant[1] :
614+
# 7| mu0_5(Int32) = Store : &:r0_3, r0_4
615+
#-----| Goto -> Block 1
616+
617+
# 7| Block 1
618+
# 7| r1_0(glval<Int32>) = VariableAddress[i] :
619+
# 7| r1_1(Int32) = Load : &:r1_0, ~mu0_2
620+
# 7| r1_2(Int32) = Constant[10] :
621+
# 7| r1_3(Boolean) = CompareLE : r1_1, r1_2
622+
# 7| v1_4(Void) = ConditionalBranch : r1_3
623+
#-----| False -> Block 7
624+
#-----| True -> Block 2
625+
626+
# 9| Block 2
627+
# 9| r2_0(glval<Int32>) = VariableAddress[i] :
628+
# 9| r2_1(Int32) = Load : &:r2_0, ~mu0_2
629+
# 9| r2_2(Int32) = Constant[3] :
630+
# 9| r2_3(Boolean) = CompareEQ : r2_1, r2_2
631+
# 9| v2_4(Void) = ConditionalBranch : r2_3
632+
#-----| False -> Block 4
633+
#-----| True -> Block 3
634+
635+
# 10| Block 3
636+
# 10| v3_0(Void) = NoOp :
637+
#-----| Goto -> Block 19
638+
639+
# 11| Block 4
640+
# 11| r4_0(glval<Int32>) = VariableAddress[i] :
641+
# 11| r4_1(Int32) = Load : &:r4_0, ~mu0_2
642+
# 11| r4_2(Int32) = Constant[5] :
643+
# 11| r4_3(Boolean) = CompareEQ : r4_1, r4_2
644+
# 11| v4_4(Void) = ConditionalBranch : r4_3
645+
#-----| False -> Block 6
646+
#-----| True -> Block 5
647+
648+
# 12| Block 5
649+
# 12| v5_0(Void) = NoOp :
650+
#-----| Goto -> Block 7
651+
652+
# 13| Block 6
653+
# 13| r6_0(glval<null>) = FunctionAddress[WriteLine] :
654+
# 13| r6_1(String) = StringConstant["BreakAndContinue"] :
655+
# 13| v6_2(Void) = Call : func:r6_0, 0:r6_1
656+
# 13| mu6_3(null) = ^CallSideEffect : ~mu0_2
657+
#-----| Goto -> Block 19
658+
659+
# 16| Block 7
660+
# 16| r7_0(glval<Int32>) = VariableAddress[a] :
661+
# 16| r7_1(Int32) = Constant[0] :
662+
# 16| mu7_2(Int32) = Store : &:r7_0, r7_1
663+
#-----| Goto -> Block 8
664+
665+
# 17| Block 8
666+
# 17| r8_0(Boolean) = Constant[true] :
667+
# 17| v8_1(Void) = ConditionalBranch : r8_0
668+
#-----| False -> Block 13
669+
#-----| True -> Block 9
670+
671+
# 19| Block 9
672+
# 19| r9_0(glval<Int32>) = VariableAddress[a] :
673+
# 19| r9_1(Int32) = Load : &:r9_0, ~mu0_2
674+
# 19| r9_2(Int32) = Constant[1] :
675+
# 19| r9_3(Int32) = Add : r9_1, r9_2
676+
# 19| mu9_4(Int32) = Store : &:r9_0, r9_3
677+
# 20| r9_5(glval<Int32>) = VariableAddress[a] :
678+
# 20| r9_6(Int32) = Load : &:r9_5, ~mu0_2
679+
# 20| r9_7(Int32) = Constant[5] :
680+
# 20| r9_8(Boolean) = CompareEQ : r9_6, r9_7
681+
# 20| v9_9(Void) = ConditionalBranch : r9_8
682+
#-----| False -> Block 11
683+
#-----| True -> Block 10
684+
685+
# 21| Block 10
686+
# 21| v10_0(Void) = NoOp :
687+
#-----| Goto (back edge) -> Block 8
688+
689+
# 22| Block 11
690+
# 22| r11_0(glval<Int32>) = VariableAddress[a] :
691+
# 22| r11_1(Int32) = Load : &:r11_0, ~mu0_2
692+
# 22| r11_2(Int32) = Constant[10] :
693+
# 22| r11_3(Boolean) = CompareEQ : r11_1, r11_2
694+
# 22| v11_4(Void) = ConditionalBranch : r11_3
695+
#-----| False (back edge) -> Block 8
696+
#-----| True -> Block 12
697+
698+
# 23| Block 12
699+
# 23| v12_0(Void) = NoOp :
700+
#-----| Goto -> Block 13
701+
702+
# 26| Block 13
703+
# 26| r13_0(glval<Int32>) = VariableAddress[i] :
704+
# 26| r13_1(Int32) = Constant[1] :
705+
# 26| mu13_2(Int32) = Store : &:r13_0, r13_1
706+
#-----| Goto -> Block 15
707+
708+
# 26| Block 14
709+
# 26| r14_0(glval<Int32>) = VariableAddress[i] :
710+
# 26| r14_1(Int32) = Load : &:r14_0, ~mu0_2
711+
# 26| r14_2(Int32) = Constant[1] :
712+
# 26| r14_3(Int32) = Add : r14_1, r14_2
713+
# 26| mu14_4(Int32) = Store : &:r14_0, r14_3
714+
#-----| Goto (back edge) -> Block 15
715+
716+
# 26| Block 15
717+
# 26| r15_0(glval<Int32>) = VariableAddress[i] :
718+
# 26| r15_1(Int32) = Load : &:r15_0, ~mu0_2
719+
# 26| r15_2(Int32) = Constant[10] :
720+
# 26| r15_3(Boolean) = CompareLE : r15_1, r15_2
721+
# 26| v15_4(Void) = ConditionalBranch : r15_3
722+
#-----| False -> Block 18
723+
#-----| True -> Block 16
724+
725+
# 28| Block 16
726+
# 28| r16_0(glval<Int32>) = VariableAddress[i] :
727+
# 28| r16_1(Int32) = Load : &:r16_0, ~mu0_2
728+
# 28| r16_2(Int32) = Constant[5] :
729+
# 28| r16_3(Boolean) = CompareEQ : r16_1, r16_2
730+
# 28| v16_4(Void) = ConditionalBranch : r16_3
731+
#-----| False -> Block 14
732+
#-----| True -> Block 17
733+
734+
# 29| Block 17
735+
# 29| v17_0(Void) = NoOp :
736+
#-----| Goto -> Block 18
737+
738+
# 31| Block 18
739+
# 31| v18_0(Void) = NoOp :
740+
# 32| r18_1(glval<null>) = FunctionAddress[WriteLine] :
741+
# 32| r18_2(String) = StringConstant["Done"] :
742+
# 32| v18_3(Void) = Call : func:r18_1, 0:r18_2
743+
# 32| mu18_4(null) = ^CallSideEffect : ~mu0_2
744+
# 5| v18_5(Void) = ReturnVoid :
745+
# 5| v18_6(Void) = UnmodeledUse : mu*
746+
# 5| v18_7(Void) = ExitFunction :
747+
748+
# 7| Block 19
749+
# 7| r19_0(glval<Int32>) = VariableAddress[i] :
750+
# 7| r19_1(Int32) = Load : &:r19_0, ~mu0_2
751+
# 7| r19_2(Int32) = Constant[1] :
752+
# 7| r19_3(Int32) = Add : r19_1, r19_2
753+
# 7| mu19_4(Int32) = Store : &:r19_0, r19_3
754+
#-----| Goto (back edge) -> Block 1
755+
606756
lock.cs:
607757
# 5| System.Void LockTest.A()
608758
# 5| Block 0

0 commit comments

Comments
 (0)