diff --git a/latte/src/main/java/typechecking/LatteTypeChecker.java b/latte/src/main/java/typechecking/LatteTypeChecker.java index 63d07c6..d7497d8 100644 --- a/latte/src/main/java/typechecking/LatteTypeChecker.java +++ b/latte/src/main/java/typechecking/LatteTypeChecker.java @@ -522,6 +522,12 @@ public void visitCtIf(CtIf ifElement) { visitCtVariableRead((CtVariableRead)condition); } else if (condition instanceof CtFieldRead){ visitCtFieldRead((CtFieldRead)condition); + } else if (condition instanceof CtInvocation) { + CtInvocation invocation = (CtInvocation) condition; + if (!invocation.getType().getQualifiedName().equals("boolean")) { + logError("Method invoked in if condition must return boolean", condition); + } + visitCtInvocation(invocation); } else { logError("Cannot evaluate the condition of the if statement: " + condition.toString(), condition); } @@ -532,11 +538,21 @@ public void visitCtIf(CtIf ifElement) { PermissionEnvironment thenPermEnv = permEnv.cloneLast(); exitScopes(); - enterScopes(); - super.visitCtBlock(ifElement.getElseStatement()); - SymbolicEnvironment elseSymbEnv = symbEnv.cloneLast(); - PermissionEnvironment elsePermEnv = permEnv.cloneLast(); - exitScopes(); + SymbolicEnvironment elseSymbEnv; + PermissionEnvironment elsePermEnv; + + if (ifElement.getElseStatement() != null) { + //Else statement + enterScopes(); + super.visitCtBlock(ifElement.getElseStatement()); + elseSymbEnv = symbEnv.cloneLast(); + elsePermEnv = permEnv.cloneLast(); + exitScopes(); + } else { + //No Else statement + elseSymbEnv = symbEnv.cloneLast(); + elsePermEnv = permEnv.cloneLast(); + } joining(thenSymbEnv, thenPermEnv, elseSymbEnv, elsePermEnv); } diff --git a/latte/src/test/examples/MyNodeAllKindsIfs.java b/latte/src/test/examples/MyNodeAllKindsIfs.java new file mode 100644 index 0000000..15ffb0a --- /dev/null +++ b/latte/src/test/examples/MyNodeAllKindsIfs.java @@ -0,0 +1,42 @@ +package latte; + +import specification.Free; +import specification.Unique; + +/* + * This file is part of the Latte test suite. + */ +class MyNode { + + @Unique Object value; + @Unique Node next; + + /** + * Constructor for the Node class using @Free value and next nodes + * @param value + * @param next + */ + public MyNode (@Free Object value, @Free Node next) { + this.value = value; + this.next = next; + } + + public void test(@Free Object v1, @Free Object v2, boolean c1, boolean c2){ + if (c1) { + this.value = v1; + } else if (c2) { + this.value = v2; + } else { + this.value = v1; + } + + if (c2) { + this.value = v1; + } else { + this.value = v2; + } + if (c1 && c2) { + this.value = v2; + } + } +} diff --git a/latte/src/test/examples/MyNodeIfNoElse.java b/latte/src/test/examples/MyNodeIfNoElse.java new file mode 100644 index 0000000..9aa847c --- /dev/null +++ b/latte/src/test/examples/MyNodeIfNoElse.java @@ -0,0 +1,29 @@ +package latte; + +import specification.Free; +import specification.Unique; + +/* + * This file is part of the Latte test suite. + */ +class MyNode { + + @Unique Object value; + @Unique Node next; + + /** + * Constructor for the Node class using @Free value and next nodes + * @param value + * @param next + */ + public MyNode (@Free Object value, @Free Node next) { + this.value = value; + this.next = next; + } + + public void test(@Free Object v1, boolean c1){ + if (c1) { + this.value = v1; + } + } +} diff --git a/latte/src/test/examples/MyNodeInvocationIf.java b/latte/src/test/examples/MyNodeInvocationIf.java new file mode 100644 index 0000000..5f44a1e --- /dev/null +++ b/latte/src/test/examples/MyNodeInvocationIf.java @@ -0,0 +1,35 @@ +package latte; + +import specification.Free; +import specification.Unique; + +/* + * This file is part of the Latte test suite. + */ +class MyNode { + + @Unique Object value; + @Unique Node next; + + /** + * Constructor for the Node class using @Free value and next nodes + * @param value + * @param next + */ + public MyNode (@Free Object value, @Free Node next) { + this.value = value; + this.next = next; + } + + public void test(@Free Object v1, boolean c1){ + if (boolRead(c1)) { + this.value = v1; + } else { + this.value = null; + } + } + + private boolean boolRead(boolean b){ + return b; + } +} diff --git a/latte/src/test/java/AppTest.java b/latte/src/test/java/AppTest.java index 8bd0f59..6b67cd4 100644 --- a/latte/src/test/java/AppTest.java +++ b/latte/src/test/java/AppTest.java @@ -40,7 +40,10 @@ private static Stream provideCorrectTestCases() { Arguments.of("src/test/examples/searching_state_space/TimerTaskCannotReschedule.java"), Arguments.of("src/test/examples/searching_state_space/ResultSetNoNext.java"), Arguments.of("src/test/examples/searching_state_space/ResultSetForwardOnly.java"), - Arguments.of("src/test/examples/stack_overflow/MediaRecord.java") + Arguments.of("src/test/examples/stack_overflow/MediaRecord.java"), + Arguments.of("src/test/examples/MyNodeAllKindsIfs.java"), + Arguments.of("src/test/examples/MyNodeIfNoElse.java"), + Arguments.of("src/test/examples/MyNodeInvocationIf.java") ); }