8327839: Crash with unboxing and widening primitive conversion in switch
Reviewed-by: jlahoda
This commit is contained in:
parent
86f1744736
commit
fb390d202c
@ -468,22 +468,23 @@ public class SwitchBootstraps {
|
||||
Label notNumber = cb.newLabel();
|
||||
cb.aload(SELECTOR_OBJ);
|
||||
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);
|
||||
} else {
|
||||
cb.ifeq(notNumber);
|
||||
}
|
||||
cb.aload(SELECTOR_OBJ);
|
||||
cb.checkcast(ConstantDescs.CD_Number);
|
||||
if (selectorType == long.class) {
|
||||
if (selectorType == long.class || selectorType == Long.class) {
|
||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
||||
"longValue",
|
||||
MethodTypeDesc.of(ConstantDescs.CD_long));
|
||||
} else if (selectorType == float.class) {
|
||||
} else if (selectorType == float.class || selectorType == Float.class) {
|
||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
||||
"floatValue",
|
||||
MethodTypeDesc.of(ConstantDescs.CD_float));
|
||||
} else if (selectorType == double.class) {
|
||||
} else if (selectorType == double.class || selectorType == Double.class) {
|
||||
cb.invokevirtual(ConstantDescs.CD_Number,
|
||||
"doubleValue",
|
||||
MethodTypeDesc.of(ConstantDescs.CD_double));
|
||||
|
@ -43,6 +43,10 @@ import combo.ComboTask;
|
||||
import combo.ComboTestHelper;
|
||||
import toolbox.ToolBox;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
import java.util.List;
|
||||
|
||||
public class PrimitiveInstanceOfComboTest extends ComboInstance<PrimitiveInstanceOfComboTest> {
|
||||
private static final String JAVA_VERSION = System.getProperty("java.specification.version");
|
||||
|
||||
@ -82,27 +86,51 @@ 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
|
||||
protected void doWork() throws Throwable {
|
||||
ComboTask task1 = newCompilationTask()
|
||||
.withSourceFromTemplate(test1.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code))
|
||||
.withOption("--enable-preview")
|
||||
.withOption("-source").withOption(JAVA_VERSION);;
|
||||
.withOption("-source").withOption(JAVA_VERSION);
|
||||
|
||||
ComboTask task2 = newCompilationTask()
|
||||
.withSourceFromTemplate(test2.replace("#{TYPE1}", type1.code).replace("#{TYPE2}", type2.code))
|
||||
.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 -> {
|
||||
task2.generate(result2 -> {
|
||||
if (result1.hasErrors() ^ result2.hasErrors()) {
|
||||
task3.generate(result3 -> {
|
||||
List<Diagnostic<? extends JavaFileObject>> list1 = result1.diagnosticsForKind(Diagnostic.Kind.ERROR);
|
||||
List<Diagnostic<? extends JavaFileObject>> list2 = result2.diagnosticsForKind(Diagnostic.Kind.ERROR);
|
||||
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 task1: " + result2.hasErrors() + ", info: " + result2.compilationInfo());
|
||||
"\n task2: " + result2.hasErrors() + ", info: " + result2.compilationInfo() +
|
||||
"\n task3: " + result3.hasErrors() + ", info: " + result3.compilationInfo()
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public enum Type implements ComboParameter {
|
||||
|
@ -113,6 +113,13 @@ public class PrimitivePatternsSwitch {
|
||||
assertEquals(1, testByteWrapperToIntUnconditionallyExact());
|
||||
assertEquals(1, testIntegerWrapperToFloat());
|
||||
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) {
|
||||
@ -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_int(int x) {}
|
||||
|
@ -241,4 +241,24 @@ public class PrimitivePatternsSwitchErrors {
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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: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: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:37: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:231: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.recompile
|
||||
37 errors
|
||||
43 errors
|
Loading…
Reference in New Issue
Block a user