From 05fb6c6648bc759853c5a9c5b932706592d87ba9 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 5 Jun 2023 06:25:00 +0000 Subject: [PATCH] 8309336: Incorrect switch in enum not reported properly Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Attr.java | 18 ++++++--- .../tools/javac/resources/compiler.properties | 6 +++ .../examples/EnumLabelMustBeEnumConstant.java | 37 +++++++++++++++++++ .../diags/examples/PatternOrEnumReq.java | 37 +++++++++++++++++++ .../patterns/PatternErrorRecovery-old.out | 2 +- .../EnumSwitchQualifiedErrors.java | 21 ++++++++++- .../switchextra/EnumSwitchQualifiedErrors.out | 8 +++- 7 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 test/langtools/tools/javac/diags/examples/EnumLabelMustBeEnumConstant.java create mode 100644 test/langtools/tools/javac/diags/examples/PatternOrEnumReq.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 12ab1c4f72565..b6ceb2a33af39 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1657,9 +1657,9 @@ private void handleSwitch(JCTree switchTree, boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0; boolean stringSwitch = types.isSameType(seltype, syms.stringType); boolean errorEnumSwitch = TreeInfo.isErrorEnumSwitch(selector, cases); + boolean intSwitch = types.isAssignable(seltype, syms.intType); boolean patternSwitch; - if (!enumSwitch && !stringSwitch && !errorEnumSwitch && - !types.isAssignable(seltype, syms.intType)) { + if (!enumSwitch && !stringSwitch && !errorEnumSwitch && !intSwitch) { preview.checkSourceLevel(selector.pos(), Feature.PATTERN_SWITCH); patternSwitch = true; } else { @@ -1706,6 +1706,10 @@ private void handleSwitch(JCTree switchTree, if (sym == null) { if (allowPatternSwitch) { attribTree(expr, switchEnv, caseLabelResultInfo(seltype)); + Symbol enumSym = TreeInfo.symbol(expr); + if (enumSym == null || !enumSym.isEnum() || enumSym.kind != VAR) { + log.error(expr.pos(), Errors.EnumLabelMustBeEnumConstant); + } } else { log.error(expr.pos(), Errors.EnumLabelMustBeUnqualifiedEnum); } @@ -1728,14 +1732,16 @@ private void handleSwitch(JCTree switchTree, if (!pattype.hasTag(ERROR)) { if (pattype.constValue() == null) { Symbol s = TreeInfo.symbol(expr); - if (s != null && s.kind == TYP && allowPatternSwitch) { + if (s != null && s.kind == TYP) { log.error(expr.pos(), Errors.PatternExpected); - } else if ((s != null && !s.isEnum()) || !allowPatternSwitch) { + } else if (s == null || !s.isEnum()) { log.error(expr.pos(), - (stringSwitch ? Errors.StringConstReq : Errors.ConstExprReq)); + (stringSwitch ? Errors.StringConstReq + : intSwitch ? Errors.ConstExprReq + : Errors.PatternOrEnumReq)); } - } else if (!stringSwitch && !types.isAssignable(seltype, syms.intType)) { + } else if (!stringSwitch && !intSwitch) { log.error(label.pos(), Errors.ConstantLabelNotCompatible(pattype, seltype)); } else if (!constants.add(pattype.constValue())) { log.error(c.pos(), Errors.DuplicateCaseLabel); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 9a2f555bb62f3..72c645461267d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -411,6 +411,9 @@ compiler.err.class.not.allowed=\ compiler.err.const.expr.req=\ constant expression required +compiler.err.pattern.or.enum.req=\ + pattern or enum constant required + compiler.err.cont.outside.loop=\ continue outside of loop @@ -576,6 +579,9 @@ compiler.err.enum.cant.be.instantiated=\ compiler.err.enum.label.must.be.unqualified.enum=\ an enum switch case label must be the unqualified name of an enumeration constant +compiler.err.enum.label.must.be.enum.constant=\ + an enum switch constant case label must be an enumeration constant + compiler.err.enum.no.subclassing=\ classes cannot directly extend java.lang.Enum diff --git a/test/langtools/tools/javac/diags/examples/EnumLabelMustBeEnumConstant.java b/test/langtools/tools/javac/diags/examples/EnumLabelMustBeEnumConstant.java new file mode 100644 index 0000000000000..176ab51b30f0b --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/EnumLabelMustBeEnumConstant.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.enum.label.must.be.enum.constant + +class EnumLabelMustBeEnumConstant { + enum E { A }; + + void m(E e) { + switch (e) { + case EA -> {} + default -> {} + } + } + + static final E EA; +} diff --git a/test/langtools/tools/javac/diags/examples/PatternOrEnumReq.java b/test/langtools/tools/javac/diags/examples/PatternOrEnumReq.java new file mode 100644 index 0000000000000..3e52cdb7ca0da --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/PatternOrEnumReq.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.pattern.or.enum.req + +class PatternOrEnumReq { + enum E { A }; + + void m(Object o) { + switch (o) { + case EA -> {} + default -> {} + } + } + + static final E EA; +} diff --git a/test/langtools/tools/javac/patterns/PatternErrorRecovery-old.out b/test/langtools/tools/javac/patterns/PatternErrorRecovery-old.out index ee25e82975236..6a149913c026e 100644 --- a/test/langtools/tools/javac/patterns/PatternErrorRecovery-old.out +++ b/test/langtools/tools/javac/patterns/PatternErrorRecovery-old.out @@ -1,3 +1,3 @@ PatternErrorRecovery.java:12:18: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.pattern.switch), 20, 21 -PatternErrorRecovery.java:11:18: compiler.err.const.expr.req +PatternErrorRecovery.java:11:18: compiler.err.pattern.expected 2 errors diff --git a/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.java b/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.java index 11767d4a1e8b1..c050ed46d52a1 100644 --- a/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.java +++ b/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8300543 + * @bug 8300543 8309336 * @summary Check switches work correctly with qualified enum constants * @compile/fail/ref=EnumSwitchQualifiedErrors.out -XDrawDiagnostics EnumSwitchQualifiedErrors.java */ @@ -51,8 +51,27 @@ int testPatternMatchingSwitch3(Number n) { }; } + int testPatternMatchingSwitch4(E1 e) { + return switch(e) { + case E1A -> 1; + case (E1) null -> 1; + case E1 -> 1; + default -> {} + }; + } + + int testPatternMatchingSwitch5(Object e) { + return switch(e) { + case E1A -> 1; + case (E1) null -> 1; + case E1 -> 1; + default -> {} + }; + } + sealed interface I {} enum E1 implements I { A; } enum E2 { A; } + static final E1 E1A = null; } diff --git a/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.out b/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.out index ff23d531c7592..d9519d81e7ec6 100644 --- a/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.out +++ b/test/langtools/tools/javac/switchextra/EnumSwitchQualifiedErrors.out @@ -2,4 +2,10 @@ EnumSwitchQualifiedErrors.java:36:20: compiler.err.prob.found.req: (compiler.mis EnumSwitchQualifiedErrors.java:43:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: EnumSwitchQualifiedErrors.E2, EnumSwitchQualifiedErrors.E1) EnumSwitchQualifiedErrors.java:49:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: EnumSwitchQualifiedErrors.E1, java.lang.Number) EnumSwitchQualifiedErrors.java:50:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: EnumSwitchQualifiedErrors.E2, java.lang.Number) -4 errors +EnumSwitchQualifiedErrors.java:56:18: compiler.err.enum.label.must.be.enum.constant +EnumSwitchQualifiedErrors.java:57:18: compiler.err.enum.label.must.be.enum.constant +EnumSwitchQualifiedErrors.java:58:18: compiler.err.enum.label.must.be.enum.constant +EnumSwitchQualifiedErrors.java:65:18: compiler.err.pattern.or.enum.req +EnumSwitchQualifiedErrors.java:66:18: compiler.err.pattern.or.enum.req +EnumSwitchQualifiedErrors.java:67:18: compiler.err.pattern.expected +10 errors