From 35d867df1f2064e867dcf1030c498bfa23568054 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 15 Jun 2021 09:04:35 +0000 Subject: [PATCH] 8268663: Crash when guards contain boolean expression Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Flow.java | 4 ++ .../tools/javac/patterns/Guards.java | 42 ++++++++++++++++++- .../tools/javac/patterns/SwitchErrors.java | 12 ++++++ .../tools/javac/patterns/SwitchErrors.out | 4 +- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index d720ac81fb9..39769687fd3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -2392,6 +2392,10 @@ private void handleSwitch(JCTree tree, JCExpression selector, JCCase c = l.head; for (JCCaseLabel pat : c.labels) { scan(pat); + if (inits.isReset()) { + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); + } } if (l.head.stats.isEmpty() && l.tail.nonEmpty() && diff --git a/test/langtools/tools/javac/patterns/Guards.java b/test/langtools/tools/javac/patterns/Guards.java index be37651f7e5..b68510571f1 100644 --- a/test/langtools/tools/javac/patterns/Guards.java +++ b/test/langtools/tools/javac/patterns/Guards.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8262891 + * @bug 8262891 8268663 * @summary Check guards implementation. * @compile --enable-preview -source ${jdk.version} Guards.java * @run main/othervm --enable-preview Guards @@ -43,6 +43,9 @@ void run() { run(this::testBooleanSwitchExpression); assertEquals("a", testPatternInGuard("a")); assertEquals(null, testPatternInGuard(1)); + runIfTrue(this::typeGuardIfTrueIfStatement); + runIfTrue(this::typeGuardIfTrueSwitchExpression); + runIfTrue(this::typeGuardIfTrueSwitchStatement); } void run(Function convert) { @@ -52,6 +55,12 @@ void run(Function convert) { assertEquals("any", convert.apply("")); } + void runIfTrue(Function convert) { + assertEquals("true", convert.apply(0)); + assertEquals("second", convert.apply(2)); + assertEquals("any", convert.apply("")); + } + String typeTestPatternSwitchTest(Object o) { switch (o) { case Integer i && i == 0: return "zero"; @@ -84,6 +93,35 @@ String testBooleanSwitchExpression(Object o) { } } + String typeGuardIfTrueSwitchStatement(Object o) { + Object o2 = ""; + switch (o) { + case Integer i && i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); return "true"; + case Integer i && i == 0 || i > 1: o = String.valueOf(i); return "second"; + case Object x: return "any"; + } + } + + String typeGuardIfTrueSwitchExpression(Object o) { + Object o2 = ""; + return switch (o) { + case Integer i && i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); yield "true"; + case Integer i && i == 0 || i > 1: o = String.valueOf(i); yield "second"; + case Object x: yield "any"; + }; + } + + String typeGuardIfTrueIfStatement(Object o) { + Object o2 = ""; + if (o != null && o instanceof (Integer i && i == 0 && i < 1) && (o = i) != null && o2 instanceof String s) { + return s != null ? "true" : null; + } else if (o != null && o instanceof (Integer i && i == 0 || i > 1) && (o = i) != null) { + return "second"; + } else { + return "any"; + } + } + String testPatternInGuard(Object o) { if (o instanceof (CharSequence cs && cs instanceof String s)) { return s; diff --git a/test/langtools/tools/javac/patterns/SwitchErrors.java b/test/langtools/tools/javac/patterns/SwitchErrors.java index e082ab6619e..422a53c135c 100644 --- a/test/langtools/tools/javac/patterns/SwitchErrors.java +++ b/test/langtools/tools/javac/patterns/SwitchErrors.java @@ -190,4 +190,16 @@ void sealedNonAbstract(SealedNonAbstract obj) { } sealed class SealedNonAbstract permits A {} final class A extends SealedNonAbstract {} + Object guardWithMatchingStatement(Object o1, Object o2) { + switch (o1) { + case String s && s.isEmpty() || o2 instanceof Number n: return n; + default: return null; + } + } + Object guardWithMatchingExpression(Object o1, Object o2) { + return switch (o1) { + case String s && s.isEmpty() || o2 instanceof Number n -> n; + default -> null; + }; + } } diff --git a/test/langtools/tools/javac/patterns/SwitchErrors.out b/test/langtools/tools/javac/patterns/SwitchErrors.out index d694b4c6800..40352f72864 100644 --- a/test/langtools/tools/javac/patterns/SwitchErrors.out +++ b/test/langtools/tools/javac/patterns/SwitchErrors.out @@ -28,6 +28,8 @@ SwitchErrors.java:166:18: compiler.err.flows.through.from.pattern SwitchErrors.java:171:27: compiler.err.flows.through.to.pattern SwitchErrors.java:177:18: compiler.err.flows.through.to.pattern SwitchErrors.java:183:13: compiler.err.pattern.dominated +SwitchErrors.java:195:76: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null) +SwitchErrors.java:201:71: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null) SwitchErrors.java:32:9: compiler.err.not.exhaustive.statement SwitchErrors.java:38:9: compiler.err.not.exhaustive.statement SwitchErrors.java:44:9: compiler.err.not.exhaustive.statement @@ -41,4 +43,4 @@ SwitchErrors.java:127:9: compiler.err.not.exhaustive.statement SwitchErrors.java:187:9: compiler.err.not.exhaustive.statement - compiler.note.preview.filename: SwitchErrors.java, DEFAULT - compiler.note.preview.recompile -41 errors +43 errors