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();
|
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));
|
||||||
|
@ -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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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) {}
|
||||||
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user