8327839: Crash with unboxing and widening primitive conversion in switch

Reviewed-by: jlahoda
This commit is contained in:
Aggelos Biboudis 2024-03-18 13:16:29 +00:00
parent 86f1744736
commit fb390d202c
5 changed files with 111 additions and 12 deletions

View File

@ -468,22 +468,23 @@ public class SwitchBootstraps {
Label notNumber = cb.newLabel(); Label notNumber = cb.newLabel();
cb.aload(SELECTOR_OBJ); cb.aload(SELECTOR_OBJ);
cb.instanceof_(ConstantDescs.CD_Number); cb.instanceof_(ConstantDescs.CD_Number);
if (selectorType == long.class || selectorType == float.class || selectorType == double.class) { if (selectorType == long.class || selectorType == float.class || selectorType == double.class ||
selectorType == Long.class || selectorType == Float.class || selectorType == Double.class) {
cb.ifeq(next); cb.ifeq(next);
} else { } else {
cb.ifeq(notNumber); cb.ifeq(notNumber);
} }
cb.aload(SELECTOR_OBJ); cb.aload(SELECTOR_OBJ);
cb.checkcast(ConstantDescs.CD_Number); cb.checkcast(ConstantDescs.CD_Number);
if (selectorType == long.class) { if (selectorType == long.class || selectorType == Long.class) {
cb.invokevirtual(ConstantDescs.CD_Number, cb.invokevirtual(ConstantDescs.CD_Number,
"longValue", "longValue",
MethodTypeDesc.of(ConstantDescs.CD_long)); MethodTypeDesc.of(ConstantDescs.CD_long));
} else if (selectorType == float.class) { } else if (selectorType == float.class || selectorType == Float.class) {
cb.invokevirtual(ConstantDescs.CD_Number, cb.invokevirtual(ConstantDescs.CD_Number,
"floatValue", "floatValue",
MethodTypeDesc.of(ConstantDescs.CD_float)); MethodTypeDesc.of(ConstantDescs.CD_float));
} else if (selectorType == double.class) { } else if (selectorType == double.class || selectorType == Double.class) {
cb.invokevirtual(ConstantDescs.CD_Number, cb.invokevirtual(ConstantDescs.CD_Number,
"doubleValue", "doubleValue",
MethodTypeDesc.of(ConstantDescs.CD_double)); MethodTypeDesc.of(ConstantDescs.CD_double));

View File

@ -43,6 +43,10 @@ import combo.ComboTask;
import combo.ComboTestHelper; import combo.ComboTestHelper;
import toolbox.ToolBox; import toolbox.ToolBox;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.util.List;
public class PrimitiveInstanceOfComboTest extends ComboInstance<PrimitiveInstanceOfComboTest> { public class PrimitiveInstanceOfComboTest extends ComboInstance<PrimitiveInstanceOfComboTest> {
private static final String JAVA_VERSION = System.getProperty("java.specification.version"); private static final String JAVA_VERSION = System.getProperty("java.specification.version");
@ -82,25 +86,49 @@ public class PrimitiveInstanceOfComboTest extends ComboInstance<PrimitiveInstanc
} }
"""; """;
// potential not-exhaustive errors are expected and filtered out in `doWork`
private static final String test3 =
"""
public class Test {
public static void doTest(#{TYPE1} in) {
switch(in) {
case #{TYPE2} x -> {}
}
}
}
""";
@Override @Override
protected void doWork() throws Throwable { protected void doWork() throws Throwable {
ComboTask task1 = newCompilationTask() ComboTask task1 = newCompilationTask()
.withSourceFromTemplate(test1.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code)) .withSourceFromTemplate(test1.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code))
.withOption("--enable-preview") .withOption("--enable-preview")
.withOption("-source").withOption(JAVA_VERSION);; .withOption("-source").withOption(JAVA_VERSION);
ComboTask task2 = newCompilationTask() ComboTask task2 = newCompilationTask()
.withSourceFromTemplate(test2.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code)) .withSourceFromTemplate(test2.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code))
.withOption("--enable-preview") .withOption("--enable-preview")
.withOption("-source").withOption(JAVA_VERSION);; .withOption("-source").withOption(JAVA_VERSION);
ComboTask task3 = newCompilationTask()
.withSourceFromTemplate(test3.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code))
.withOption("--enable-preview")
.withOption("-source").withOption(JAVA_VERSION);
task1.generate(result1 -> { task1.generate(result1 -> {
task2.generate(result2 -> { task2.generate(result2 -> {
if (result1.hasErrors() ^ result2.hasErrors()) { task3.generate(result3 -> {
throw new AssertionError("Unexpected result: " + List<Diagnostic<? extends JavaFileObject>> list1 = result1.diagnosticsForKind(Diagnostic.Kind.ERROR);
"\n task1: " + result1.hasErrors() + ", info: " + result1.compilationInfo() + List<Diagnostic<? extends JavaFileObject>> list2 = result2.diagnosticsForKind(Diagnostic.Kind.ERROR);
"\n task1: " + result2.hasErrors() + ", info: " + result2.compilationInfo()); List<Diagnostic<? extends JavaFileObject>> list3 = result3.diagnosticsForKind(Diagnostic.Kind.ERROR).stream().filter(e -> !e.getCode().equals("compiler.err.not.exhaustive.statement")).toList();
} if (!(list1.size() == list2.size() && list3.size() == list2.size())) {
throw new AssertionError("Unexpected result: " +
"\n task1: " + result1.hasErrors() + ", info: " + result1.compilationInfo() +
"\n task2: " + result2.hasErrors() + ", info: " + result2.compilationInfo() +
"\n task3: " + result3.hasErrors() + ", info: " + result3.compilationInfo()
);
}
});
}); });
}); });
} }

View File

@ -113,6 +113,13 @@ public class PrimitivePatternsSwitch {
assertEquals(1, testByteWrapperToIntUnconditionallyExact()); assertEquals(1, testByteWrapperToIntUnconditionallyExact());
assertEquals(1, testIntegerWrapperToFloat()); assertEquals(1, testIntegerWrapperToFloat());
assertEquals(-1, testIntegerWrapperToFloatInexact()); assertEquals(-1, testIntegerWrapperToFloatInexact());
assertEquals(Character.MAX_VALUE, testUnboxingAndWideningCharacter1(Character.MAX_VALUE));
assertEquals(Character.MAX_VALUE, testUnboxingAndWideningCharacter2(Character.MAX_VALUE));
assertEquals(Character.MAX_VALUE, testUnboxingAndWideningCharacter3(Character.MAX_VALUE));
assertEquals(Float.MAX_VALUE, testUnboxingAndWideningFloat(Float.MAX_VALUE));
assertEquals(Float.MAX_VALUE, testUnboxingAndWideningFloatExplicitCast(Float.MAX_VALUE));
assertEquals(42f, testUnboxingAndWideningLong(42L));
assertEquals(2, testUnboxingAndWideningLong(Long.MAX_VALUE));
} }
public static int primitiveSwitch(int i) { public static int primitiveSwitch(int i) {
@ -565,6 +572,43 @@ public class PrimitivePatternsSwitch {
}; };
} }
public static char testUnboxingAndWideningCharacter1(Character test) {
return switch (test) {
case char c -> c;
};
}
public static int testUnboxingAndWideningCharacter2(Character test) {
return switch (test) {
case int c -> c;
};
}
public static float testUnboxingAndWideningCharacter3(Character test) {
return switch (test) {
case float f -> f;
};
}
public static float testUnboxingAndWideningLong(Long test) {
return switch (test) {
case float y -> y;
default -> 2;
};
}
public static double testUnboxingAndWideningFloat(Float test) {
return switch (test) {
case double y -> y;
default -> 2;
};
}
public static double testUnboxingAndWideningFloatExplicitCast(Object test) {
return switch ((Float) test) {
case double y -> y;
default -> 2;
};
}
record R_Integer(Integer x) {} record R_Integer(Integer x) {}
record R_int(int x) {} record R_int(int x) {}

View File

@ -241,4 +241,24 @@ public class PrimitivePatternsSwitchErrors {
case int b -> -2 ; case int b -> -2 ;
}; };
} }
public static int disallowedUnboxingAndNarrowing1() {
Long n = 42l;
return switch (n) { // Error - not exhaustive and not allowed
case char c -> -1 ;
};
}
public static int disallowedUnboxingAndNarrowing2() {
Long n = 42l;
return switch (n) { // Error - not exhaustive and not allowed
case int c -> -1 ;
};
}
public static char disallowedUnboxingAndWidening(Short test) {
return switch (test) {
case char c -> c; // Error - not exhaustive and not allowed
};
}
} }

View File

@ -26,6 +26,9 @@ PrimitivePatternsSwitchErrors.java:179:18: compiler.err.prob.found.req: (compile
PrimitivePatternsSwitchErrors.java:189:18: compiler.err.unconditional.pattern.and.both.boolean.values PrimitivePatternsSwitchErrors.java:189:18: compiler.err.unconditional.pattern.and.both.boolean.values
PrimitivePatternsSwitchErrors.java:196:18: compiler.err.duplicate.unconditional.pattern PrimitivePatternsSwitchErrors.java:196:18: compiler.err.duplicate.unconditional.pattern
PrimitivePatternsSwitchErrors.java:216:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, int) PrimitivePatternsSwitchErrors.java:216:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, int)
PrimitivePatternsSwitchErrors.java:248:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Long, char)
PrimitivePatternsSwitchErrors.java:255:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Long, int)
PrimitivePatternsSwitchErrors.java:261:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Short, char)
PrimitivePatternsSwitchErrors.java:30:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:30:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:37:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:37:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:44:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:44:16: compiler.err.not.exhaustive
@ -35,6 +38,9 @@ PrimitivePatternsSwitchErrors.java:207:9: compiler.err.not.exhaustive.statement
PrimitivePatternsSwitchErrors.java:223:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:223:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:231:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:231:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:239:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:239:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:247:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:254:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:260:16: compiler.err.not.exhaustive
- compiler.note.preview.filename: PrimitivePatternsSwitchErrors.java, DEFAULT - compiler.note.preview.filename: PrimitivePatternsSwitchErrors.java, DEFAULT
- compiler.note.preview.recompile - compiler.note.preview.recompile
37 errors 43 errors