Skip to content

Commit 90ad25a

Browse files
jgardn3rcirras
authored andcommitted
Terminate Finally control flow graph blocks with FinallyBlockNode
1 parent 8558d42 commit 90ad25a

File tree

4 files changed

+62
-20
lines changed

4 files changed

+62
-20
lines changed

delphi-frontend/src/main/java/au/com/integradev/delphi/cfg/ControlFlowGraphVisitor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ private ControlFlowGraphBuilder buildTryFinally(
531531
// Finally
532532
FinallyBlockNode finallyNode = node.getFinallyBlock();
533533
builder.addBlock(
534-
ProtoBlockFactory.finallyBlock(builder.getCurrentBlock(), builder.getExitBlock()));
534+
ProtoBlockFactory.finallyBlock(
535+
node.getFinallyBlock(), builder.getCurrentBlock(), builder.getExitBlock()));
536+
535537
build(finallyNode.getStatementList(), builder);
536538
builder.pushLoopContext(builder.getCurrentBlock(), builder.getCurrentBlock());
537539
builder.pushExitBlock(builder.getCurrentBlock());

delphi-frontend/src/main/java/au/com/integradev/delphi/cfg/api/Finally.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import java.util.Set;
2424

2525
/** A {@code finally} block whose control flow depends on the existence of previous exceptions */
26-
public interface Finally extends Block {
26+
public interface Finally extends Block, Terminated {
2727
/**
2828
* Next block in the {@link ControlFlowGraph} without exceptional circumstances
2929
*

delphi-frontend/src/main/java/au/com/integradev/delphi/cfg/block/ProtoBlockFactory.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.Set;
3434
import java.util.stream.Collectors;
3535
import org.sonar.plugins.communitydelphi.api.ast.DelphiNode;
36+
import org.sonar.plugins.communitydelphi.api.ast.FinallyBlockNode;
3637

3738
public final class ProtoBlockFactory {
3839
private ProtoBlockFactory() {
@@ -56,11 +57,13 @@ public static ProtoBlock branch(
5657
.setData(terminator, blocks.get(trueBlock), blocks.get(falseBlock)));
5758
}
5859

59-
public static ProtoBlock finallyBlock(ProtoBlock successor, ProtoBlock finallySuccessor) {
60+
public static ProtoBlock finallyBlock(
61+
FinallyBlockNode terminator, ProtoBlock successor, ProtoBlock finallySuccessor) {
6062
return new ProtoBlock(
6163
FinallyImpl::new,
6264
(blocks, block) ->
63-
((FinallyImpl) block).setData(blocks.get(successor), blocks.get(finallySuccessor)));
65+
((FinallyImpl) block)
66+
.setData(terminator, blocks.get(successor), blocks.get(finallySuccessor)));
6467
}
6568

6669
public static ProtoBlock linear(ProtoBlock successor) {
@@ -295,14 +298,16 @@ public String getBlockType() {
295298
static class FinallyImpl extends BlockImpl implements Finally {
296299
private Block successor;
297300
private Block exceptionSuccessor;
301+
private Terminator terminator;
298302

299303
protected FinallyImpl(List<DelphiNode> elements) {
300304
super(elements);
301305
}
302306

303-
public void setData(Block successor, Block exitSuccessor) {
307+
public void setData(FinallyBlockNode node, Block successor, Block exitSuccessor) {
304308
this.successor = successor;
305309
this.exceptionSuccessor = exitSuccessor;
310+
this.terminator = new Terminator(node);
306311
}
307312

308313
@Override
@@ -315,6 +320,16 @@ public Block getExceptionSuccessor() {
315320
return exceptionSuccessor;
316321
}
317322

323+
@Override
324+
public DelphiNode getTerminator() {
325+
return terminator.getTerminatorNode();
326+
}
327+
328+
@Override
329+
public TerminatorKind getTerminatorKind() {
330+
return terminator.getKind();
331+
}
332+
318333
@Override
319334
public void replaceInactiveSuccessor(Block inactiveBlock, Block target) {
320335
this.successor = getNewTarget(this.successor, inactiveBlock, target);

delphi-frontend/src/test/java/au/com/integradev/delphi/cfg/ControlFlowGraphTest.java

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.sonar.plugins.communitydelphi.api.ast.CaseStatementNode;
6060
import org.sonar.plugins.communitydelphi.api.ast.CommonDelphiNode;
6161
import org.sonar.plugins.communitydelphi.api.ast.DelphiNode;
62+
import org.sonar.plugins.communitydelphi.api.ast.FinallyBlockNode;
6263
import org.sonar.plugins.communitydelphi.api.ast.ForInStatementNode;
6364
import org.sonar.plugins.communitydelphi.api.ast.ForToStatementNode;
6465
import org.sonar.plugins.communitydelphi.api.ast.GotoStatementNode;
@@ -818,7 +819,9 @@ void testTryFinallyNoRaise() {
818819
checker(
819820
block(element(TryStatementNode.class)).succeedsTo(2),
820821
block(element(NameReferenceNode.class, "Foo")).succeedsToWithExceptions(1, 1),
821-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(0, 0)));
822+
block(element(NameReferenceNode.class, "Bar"))
823+
.withTerminator(FinallyBlockNode.class)
824+
.succeedsToWithExit(0, 0)));
822825
}
823826

824827
@Test
@@ -830,7 +833,9 @@ void testTryFinallyRaise() {
830833
block(element(NameReferenceNode.class, "E"))
831834
.withTerminator(RaiseStatementNode.class, TerminatorKind.RAISE)
832835
.jumpsTo(1, 1),
833-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(0, 0)));
836+
block(element(NameReferenceNode.class, "Bar"))
837+
.withTerminator(FinallyBlockNode.class)
838+
.succeedsToWithExit(0, 0)));
834839
}
835840

836841
@Test
@@ -840,7 +845,9 @@ void testTryFinallyExit() {
840845
checker(
841846
block(element(TryStatementNode.class)).succeedsTo(2),
842847
terminator(StatementTerminator.EXIT).jumpsTo(1, 1),
843-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(0, 0)));
848+
block(element(NameReferenceNode.class, "Bar"))
849+
.withTerminator(FinallyBlockNode.class)
850+
.succeedsToWithExit(0, 0)));
844851
}
845852

846853
@Test
@@ -853,7 +860,9 @@ void testTryFinallyBreak() {
853860
.withTerminator(WhileStatementNode.class),
854861
block(element(TryStatementNode.class)).succeedsTo(2),
855862
terminator(StatementTerminator.BREAK).jumpsTo(1, 1),
856-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(4, 0)));
863+
block(element(NameReferenceNode.class, "Bar"))
864+
.withTerminator(FinallyBlockNode.class)
865+
.succeedsToWithExit(4, 0)));
857866
}
858867

859868
@Test
@@ -866,7 +875,9 @@ void testTryFinallyContinue() {
866875
.withTerminator(WhileStatementNode.class),
867876
block(element(TryStatementNode.class)).succeedsTo(2),
868877
terminator(StatementTerminator.CONTINUE).jumpsTo(1, 1),
869-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(4, 0)));
878+
block(element(NameReferenceNode.class, "Bar"))
879+
.withTerminator(FinallyBlockNode.class)
880+
.succeedsToWithExit(4, 0)));
870881
}
871882

872883
@Test
@@ -876,7 +887,9 @@ void testTryFinallyHalt() {
876887
checker(
877888
block(element(TryStatementNode.class)).succeedsTo(2),
878889
terminator(StatementTerminator.HALT).isSink(),
879-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(0, 0)));
890+
block(element(NameReferenceNode.class, "Bar"))
891+
.withTerminator(FinallyBlockNode.class)
892+
.succeedsToWithExit(0, 0)));
880893
}
881894

882895
@Test
@@ -894,7 +907,9 @@ void testTryContinueFinallyInLoop() {
894907
block(element(IntegerLiteralNode.class)).succeedsTo(1),
895908
block(element(TryStatementNode.class)).succeedsTo(3),
896909
terminator(StatementTerminator.CONTINUE).jumpsTo(2, 2),
897-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(1, 0),
910+
block(element(NameReferenceNode.class, "Bar"))
911+
.withTerminator(FinallyBlockNode.class)
912+
.succeedsToWithExit(1, 0),
898913
block(element(NameDeclarationNode.class, "A"))
899914
.branchesTo(4, 0)
900915
.withTerminator(ForToStatementNode.class)));
@@ -915,7 +930,9 @@ void testTryBreakFinallyInLoop() {
915930
block(element(IntegerLiteralNode.class)).succeedsTo(1),
916931
block(element(TryStatementNode.class)).succeedsTo(3),
917932
terminator(StatementTerminator.BREAK).jumpsTo(2, 2),
918-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(1, 0),
933+
block(element(NameReferenceNode.class, "Bar"))
934+
.withTerminator(FinallyBlockNode.class)
935+
.succeedsToWithExit(1, 0),
919936
block(element(NameDeclarationNode.class, "A"))
920937
.branchesTo(4, 0)
921938
.withTerminator(ForToStatementNode.class)));
@@ -936,7 +953,9 @@ void testTryExitFinallyInLoop() {
936953
block(element(IntegerLiteralNode.class)).succeedsTo(1),
937954
block(element(TryStatementNode.class)).succeedsTo(3),
938955
terminator(StatementTerminator.EXIT).jumpsTo(2, 2),
939-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(1, 0),
956+
block(element(NameReferenceNode.class, "Bar"))
957+
.succeedsToWithExit(1, 0)
958+
.withTerminator(FinallyBlockNode.class),
940959
block(element(NameDeclarationNode.class, "A"))
941960
.branchesTo(4, 0)
942961
.withTerminator(ForToStatementNode.class)));
@@ -957,7 +976,9 @@ void testTryHaltFinallyInLoop() {
957976
block(element(IntegerLiteralNode.class)).succeedsTo(1),
958977
block(element(TryStatementNode.class)).succeedsTo(3),
959978
terminator(StatementTerminator.HALT).isSink(),
960-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(1, 0),
979+
block(element(NameReferenceNode.class, "Bar"))
980+
.succeedsToWithExit(1, 0)
981+
.withTerminator(FinallyBlockNode.class),
961982
block(element(NameDeclarationNode.class, "A"))
962983
.branchesTo(4, 0)
963984
.withTerminator(ForToStatementNode.class)));
@@ -971,7 +992,9 @@ void testTryExceptNoRaise() {
971992
checker(
972993
block(element(TryStatementNode.class)).succeedsTo(2),
973994
block(element(NameReferenceNode.class, "Foo")).succeedsToWithExceptions(1, 1),
974-
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExit(0, 0)));
995+
block(element(NameReferenceNode.class, "Bar"))
996+
.withTerminator(FinallyBlockNode.class)
997+
.succeedsToWithExit(0, 0)));
975998
}
976999

9771000
@Test
@@ -1128,7 +1151,9 @@ void testNestedTryExceptFinally() {
11281151
block(element(NameReferenceNode.class, "Foo")).succeedsToWithExceptions(1, 1, 2),
11291152
block(element(NameDeclarationNode.class, "E"), element(NameReferenceNode.class, "Bar"))
11301153
.succeedsToWithExceptions(1, 1),
1131-
block(element(NameReferenceNode.class, "Baz")).succeedsToWithExit(0, 0)));
1154+
block(element(NameReferenceNode.class, "Baz"))
1155+
.withTerminator(FinallyBlockNode.class)
1156+
.succeedsToWithExit(0, 0)));
11321157
}
11331158

11341159
@Test
@@ -1146,7 +1171,7 @@ void testNestedTryFinallyExcept() {
11461171
block(element(TryStatementNode.class)).succeedsTo(5),
11471172
block(element(NameReferenceNode.class, "Foo")).succeedsToWithExceptions(4, 4),
11481173
block(element(NameReferenceNode.class, "Bar")).succeedsToWithExceptions(3, 0, 1),
1149-
block().succeedsToWithExit(2, 0),
1174+
terminator(FinallyBlockNode.class).succeedsToWithExit(2, 0),
11501175
block().succeedsToWithExceptions(0, 0, 1),
11511176
block(element(NameDeclarationNode.class, "E"), element(NameReferenceNode.class, "Baz"))
11521177
.succeedsTo(0)));
@@ -1205,7 +1230,7 @@ void testEmptyTryFinally() {
12051230
"try finally end; A",
12061231
checker(
12071232
block(element(TryStatementNode.class)).succeedsTo(2),
1208-
block().succeedsToWithExit(1, 0),
1233+
terminator(FinallyBlockNode.class).succeedsToWithExit(1, 0),
12091234
block(element(NameReferenceNode.class, "A")).succeedsTo(0)));
12101235
}
12111236

@@ -1568,7 +1593,7 @@ void testComplexConstructions() {
15681593
.succeedsTo(2),
15691594
block(element(TextLiteralNode.class, "'b'"), element(NameReferenceNode.class, "X"))
15701595
.succeedsTo(2),
1571-
block().succeedsToWithExit(12, 0),
1596+
terminator(FinallyBlockNode.class).succeedsToWithExit(12, 0),
15721597
block(element(NameReferenceNode.class, "Foo4")).succeedsTo(0)));
15731598
}
15741599
}

0 commit comments

Comments
 (0)