Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2020-07-19 07:35:10 +0000
committerManoj Palat2020-07-19 07:36:25 +0000
commit12cac2354732e0b1e75a0ebb5e1df3f61743ea15 (patch)
treeac29393f77331caee00aa6d71cd72fde1ac78420
parent55cd7fdcd2486170b7f6a341015cae5df037d88f (diff)
downloadeclipse.jdt.core-I20200719-2010.tar.gz
eclipse.jdt.core-I20200719-2010.tar.xz
eclipse.jdt.core-I20200719-2010.zip
Bug 565156 - Compiler crash on switch expressions with try-catch andI20200719-2010
throw Change-Id: Ib0531d06d0223758b8928397a4a2e3d8b36e2a37 Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java227
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java118
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java4
5 files changed, 314 insertions, 44 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
index 0cb6f7e8fc..32df1d186f 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
@@ -26,7 +26,7 @@ public class SwitchExpressionsYieldTest extends AbstractRegressionTest {
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "testBug561766" };
+// TESTS_NAMES = new String[] { "testBug545567_14" };
}
public static Class<?> testClass() {
@@ -5192,4 +5192,229 @@ public class SwitchExpressionsYieldTest extends AbstractRegressionTest {
"The target type of this expression must be a functional interface\n" +
"----------\n");
}
+ public void testBug565156_001() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public int test() {\n"+
+ " return switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 0;\n"+
+ " }\n"+
+ " catch (RuntimeException e) {\n"+
+ " throw e;\n"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " } \n"+
+ " public static void main(String[] args) {\n"+
+ " int i = new X().test();\n"+
+ " System.out.println(i);\n"+
+ " }\n"+
+ "}\n"
+ },
+ "0");
+ }
+ public void testBug565156_002() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public int test() {\n"+
+ " return switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 0;\n"+
+ " }\n"+
+ " finally {\n"+
+ " //do nothing\n"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " } \n"+
+ " public static void main(String[] args) {\n"+
+ " int i = new X().test();\n"+
+ " System.out.println(i);\n"+
+ " }\n"+
+ "}\n"
+ },
+ "0");
+ }
+ public void testBug565156_003() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public int test() {\n"+
+ " return switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 0;\n"+
+ " }\n"+
+ " finally {\n"+
+ " int i = 20;"+
+ " yield 20;"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " } \n"+
+ " public static void main(String[] args) {\n"+
+ " int i = new X().test();\n"+
+ " System.out.println(i);\n"+
+ " }\n"+
+ "}\n"
+ },
+ "20");
+ }
+ public void testBug565156_004() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public int test() {\n"+
+ " return switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 100;\n"+
+ " }\n"+
+ " finally {\n"+
+ " yield 200; \n"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " }\n"+
+ " finally {\n"+
+ " yield 20;\n"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " }\n"+
+ " public static void main(String[] args){\n"+
+ " int i = new X().test();\n"+
+ " System.out.println(i);\n"+
+ " }\n"+
+ "}"
+ },
+ "20");
+ }
+ public void testBug565156_005() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public int test() {\n"+
+ " return switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 100;\n"+
+ " }\n"+
+ " finally {\n"+
+ " // do nothing\n"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " }\n"+
+ " finally {\n"+
+ " // do nothing\n"+
+ " }\n"+
+ " }\n"+
+ " };\n"+
+ " }\n"+
+ " public static void main(String[] args){\n"+
+ " int i = new X().test();\n"+
+ " System.out.println(i);\n"+
+ " }\n"+
+ "}"
+ },
+ "100");
+ }
+ public void testBug565156_006() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public static void main(String[] args) {\n"+
+ " new X().foo(args);\n"+
+ " }\n"+
+ "\n"+
+ " @SuppressWarnings({ \"finally\" })\n"+
+ " public void foo(String[] args) {\n"+
+ " int t = switch (0) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " if (args == null)\n"+
+ " yield 1;\n"+
+ " else if (args.length ==2)\n"+
+ " yield 2; \n"+
+ " else if (args.length == 4)\n"+
+ " yield 4;\n"+
+ " else yield 5; \n"+
+ " } finally {\n"+
+ " yield 3; \n"+
+ " }\n"+
+ " }\n"+
+ " }; \n"+
+ " t = switch (100) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 10;\n"+
+ " } finally {\n"+
+ " }\n"+
+ " } \n"+
+ " }; \n"+
+ " System.out.println(t);\n"+
+ " }\n"+
+ "}"
+ },
+ "10");
+ }
+ public void testBug565156_007() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " public static void main(String[] args) {\n"+
+ " new X().foo(args);\n"+
+ " }\n"+
+ "\n"+
+ " @SuppressWarnings({ \"finally\" })\n"+
+ " public void foo(String[] args) {\n"+
+ " int t = switch (0) {\n"+
+ " case 101 -> {yield 101;}\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " if (args == null)\n"+
+ " yield 1;\n"+
+ " else if (args.length ==2)\n"+
+ " yield 2; \n"+
+ " else if (args.length == 4)\n"+
+ " yield 4;\n"+
+ " else yield 5; \n"+
+ " } finally {\n"+
+ " yield 3; \n"+
+ " }\n"+
+ " }\n"+
+ " }; \n"+
+ " t = switch (100) {\n"+
+ " default -> {\n"+
+ " try {\n"+
+ " yield 10;\n"+
+ " } finally {\n"+
+ " }\n"+
+ " } \n"+
+ " }; \n"+
+ " System.out.println(t);\n"+
+ " }\n"+
+ "}"
+ },
+ "10");
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
index 62904f9308..59522dfa93 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
@@ -32,12 +32,6 @@ public BranchStatement(char[] label, int sourceStart,int sourceEnd) {
this.sourceEnd = sourceEnd;
}
-protected void generateExpressionResultCode(BlockScope currentScope, CodeStream codeStream) {
- // do nothing here
-}
-protected void adjustStackSize(BlockScope currentScope, CodeStream codeStream) {
- // do nothing here
-}
protected void setSubroutineSwitchExpression(SubRoutineStatement sub) {
// Do nothing
}
@@ -54,7 +48,6 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
if ((this.bits & ASTNode.IsReachable) == 0) {
return;
}
- generateExpressionResultCode(currentScope, codeStream);
int pc = codeStream.position;
// generation of code responsible for invoking the finally
@@ -80,7 +73,6 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
}
// checkAndLoadSyntheticVars(codeStream);
codeStream.goto_(this.targetLabel);
- adjustStackSize(currentScope, codeStream);
codeStream.recordPositionsFrom(pc, this.sourceStart);
SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream);
if (this.initStateIndex != -1) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
index e0c96327b4..3e258e3ebe 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
@@ -302,6 +302,7 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
public void loadStoredTypesAndKeep(CodeStream codeStream) {
List<LocalVariableBinding> tos = this.typesOnStack;
int sz = tos != null ? tos.size() : 0;
+ codeStream.clearTypeBindingStack();
int index = sz - 1;
while (index >= 0) {
LocalVariableBinding lvb = tos.get(index--);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java
index 84a9106bc7..f626942837 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/YieldStatement.java
@@ -127,44 +127,96 @@ protected void addSecretYieldResultValue(BlockScope scope1) {
protected void restartExceptionLabels(CodeStream codeStream) {
SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream);
}
-@Override
-protected void generateExpressionResultCode(BlockScope currentScope, CodeStream codeStream) {
+protected void generateExpressionResultCodeExpanded(BlockScope currentScope, CodeStream codeStream) {
SwitchExpression se = this.switchExpression;
- if (se != null && se.containsTry && se.resolvedType != null ) {
- addSecretYieldResultValue(this.scope);
- assert this.secretYieldResultValue != null;
- codeStream.record(this.secretYieldResultValue);
- SingleNameReference lhs = new SingleNameReference(this.secretYieldResultValue.name, 0);
- lhs.binding = this.secretYieldResultValue;
- lhs.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
- lhs.bits |= Binding.LOCAL;
- lhs.bits |= ASTNode.IsSecretYieldValueUsage;
- ((LocalVariableBinding) lhs.binding).markReferenced(); // TODO : Can be skipped?
- Assignment assignment = new Assignment(lhs, this.expression, 0);
- assignment.generateCode(this.scope, codeStream);
- int l = this.subroutines == null ? 0 : this.subroutines.length;
- boolean foundFinally = false;
- if (l > 0) {
- for (int i = 0; i < l; ++i) {
- SubRoutineStatement srs = this.subroutines[i];
- srs.exitAnyExceptionHandler();
- srs.exitDeclaredExceptionHandlers(codeStream);
- if (srs instanceof TryStatement) {
- TryStatement ts = (TryStatement) srs;
- if (ts.finallyBlock != null) {
- foundFinally = true;
+ addSecretYieldResultValue(this.scope);
+ assert this.secretYieldResultValue != null;
+ codeStream.record(this.secretYieldResultValue);
+ SingleNameReference lhs = new SingleNameReference(this.secretYieldResultValue.name, 0);
+ lhs.binding = this.secretYieldResultValue;
+ lhs.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
+ lhs.bits |= Binding.LOCAL;
+ lhs.bits |= ASTNode.IsSecretYieldValueUsage;
+ ((LocalVariableBinding) lhs.binding).markReferenced(); // TODO : Can be skipped?
+ Assignment assignment = new Assignment(lhs, this.expression, 0);
+ assignment.generateCode(this.scope, codeStream);
+
+ int pc = codeStream.position;
+ // generation of code responsible for invoking the finally
+ // blocks in sequence
+ if (this.subroutines != null){
+ for (int i = 0, max = this.subroutines.length; i < max; i++){
+ SubRoutineStatement sub = this.subroutines[i];
+ sub.exitAnyExceptionHandler();
+ sub.exitDeclaredExceptionHandlers(codeStream);
+ SwitchExpression se1 = sub.getSwitchExpression();
+ setSubroutineSwitchExpression(sub);
+ boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, this.targetLabel, this.initStateIndex, null);
+ sub.setSwitchExpression(se1);
+ if (didEscape) {
+ codeStream.removeVariable(this.secretYieldResultValue);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
+ if (this.initStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
}
- }
+ restartExceptionLabels(codeStream);
+ return;
}
}
- if (!foundFinally) {
- // no finally - TODO: Check for SynSta?
- se.loadStoredTypesAndKeep(codeStream);
- codeStream.load(this.secretYieldResultValue);
+ }
+ se.loadStoredTypesAndKeep(codeStream);
+ codeStream.load(this.secretYieldResultValue);
+ codeStream.removeVariable(this.secretYieldResultValue);
+
+ codeStream.goto_(this.targetLabel);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream);
+ if (this.initStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
+ }
+}
+@Override
+public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+ if ((this.bits & ASTNode.IsReachable) == 0) {
+ return;
+ }
+ if (this.switchExpression != null && this.switchExpression.containsTry && this.switchExpression.resolvedType != null ) {
+ generateExpressionResultCodeExpanded(currentScope, codeStream);
+ return;
+ }
+ this.expression.generateCode(this.scope, codeStream, this.switchExpression != null);
+ int pc = codeStream.position;
+
+ // generation of code responsible for invoking the finally
+ // blocks in sequence
+ if (this.subroutines != null){
+ for (int i = 0, max = this.subroutines.length; i < max; i++){
+ SubRoutineStatement sub = this.subroutines[i];
+ SwitchExpression se = sub.getSwitchExpression();
+ setSubroutineSwitchExpression(sub);
+ boolean didEscape = sub.generateSubRoutineInvocation(currentScope, codeStream, this.targetLabel, this.initStateIndex, null);
+ sub.setSwitchExpression(se);
+ if (didEscape) {
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, i, codeStream);
+ if (this.initStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
+ }
+ restartExceptionLabels(codeStream);
+ return;
+ }
}
- codeStream.removeVariable(this.secretYieldResultValue);
- } else {
- this.expression.generateCode(this.scope, codeStream, se != null);
+ }
+ codeStream.goto_(this.targetLabel);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ SubRoutineStatement.reenterAllExceptionHandlers(this.subroutines, -1, codeStream);
+ if (this.initStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.initStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, this.initStateIndex);
}
}
private boolean isInsideTry() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index 393398afcf..ddf658f3a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -6823,7 +6823,7 @@ public void pop2() {
public void pushExceptionOnStack(TypeBinding binding) {
this.stackDepth = 1;
- clearTypeBindingStack();
+// clearTypeBindingStack();
pushTypeBinding(binding);
if (this.stackDepth > this.stackMax)
this.stackMax = this.stackDepth;
@@ -7689,7 +7689,7 @@ private void popTypeBinding(int nPop) {
for (int i = 0; i< nPop; ++i)
popTypeBinding();
}
-private void clearTypeBindingStack() {
+public void clearTypeBindingStack() {
if (!isSwitchStackTrackingActive())
return;
this.switchSaveTypeBindings.clear();

Back to the top