8309336: Incorrect switch in enum not reported properly

Reviewed-by: vromero
This commit is contained in:
Jan Lahoda 2023-06-05 06:25:00 +00:00
parent 08c91c2212
commit 05fb6c6648
7 changed files with 120 additions and 9 deletions
src/jdk.compiler/share/classes/com/sun/tools/javac
test/langtools/tools/javac

@ -1657,9 +1657,9 @@ public class Attr extends JCTree.Visitor {
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 @@ public class Attr extends JCTree.Visitor {
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 @@ public class Attr extends JCTree.Visitor {
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);

@ -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

@ -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;
}

@ -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;
}

@ -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

@ -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 @@ public class EnumSwitchQualifiedErrors {
};
}
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;
}

@ -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