# HG changeset patch # User Christian Humer # Date 1420205511 -3600 # Node ID 2c669386b5d017dc62fe32aab8363fe191c0c546 # Parent 144fba40c9796a43d17aaefcd68de09ed45b1778 Truffle-DSL: fix crash if type in rewriteOn is not of type Throwable. Improved error messages for Specialization#rewriteOn. diff -r 144fba40c979 -r 2c669386b5d0 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Wed Dec 31 17:35:10 2014 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Fri Jan 02 14:31:51 2015 +0100 @@ -334,36 +334,37 @@ } + /* Throwing RuntimeExceptions without rewriteOn is allowed. */ @NodeChildren({@NodeChild("a")}) - static class FallthroughTest6 extends ValueNode { + static class FallthroughExceptionType0 extends ValueNode { - static int fallthrough1; - static int fallthrough2; - static int fallthrough3; - static int fallthrough4; - - @Specialization(order = 1, rewriteOn = ArithmeticException.class) - int do4(int a) throws ArithmeticException { + @Specialization + int do4(int a) throws RuntimeException { return a; } - @Specialization(order = 2, rewriteOn = ArithmeticException.class) - int do2(int a) throws ArithmeticException { + } + + /* Non runtime exceptions must be verified. */ + @NodeChildren({@NodeChild("a")}) + static class FallthroughExceptionType1 extends ValueNode { + + @ExpectError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @Specialization method must specify a throws clause with the exception type 'java.lang.Throwable'.") + @Specialization(rewriteOn = Throwable.class) + int do4(int a) { return a; } - @Specialization(order = 3, rewriteOn = ArithmeticException.class) - int do3(int a) throws ArithmeticException { - return a; - } + } - @Specialization(order = 4, rewriteOn = ArithmeticException.class) - int do1(int a) throws ArithmeticException { - return a; - } + /* Checked exception must be verified. */ + @NodeChildren({@NodeChild("a")}) + static class FallthroughExceptionType2 extends ValueNode { + @ExpectError("A checked exception 'java.lang.Throwable' is thrown but is not specified using the rewriteOn property. " + + "Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.") @Specialization - double do5(double a) { + int do4(int a) throws Throwable { return a; } diff -r 144fba40c979 -r 2c669386b5d0 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Wed Dec 31 17:35:10 2014 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Fri Jan 02 14:31:51 2015 +0100 @@ -988,9 +988,7 @@ } // search for any super types - TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); - List superTypes = getSuperTypes(exceptionTypeElement); - for (TypeElement typeElement : superTypes) { + for (TypeElement typeElement : getSuperTypes(fromTypeMirror(exceptionType))) { if (ElementUtils.containsType(thrownTypes, typeElement.asType())) { return true; } @@ -1022,11 +1020,7 @@ private static boolean isRuntimeException(TypeMirror type) { Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); - String typeName = getQualifiedName(type); - if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { - throw new IllegalArgumentException("Given type does not extend Throwable."); - } - return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); + return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || getQualifiedName(type).equals(RuntimeException.class.getCanonicalName()); } private static boolean containsType(Collection collection, TypeMirror type) { diff -r 144fba40c979 -r 2c669386b5d0 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Wed Dec 31 17:35:10 2014 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Fri Jan 02 14:31:51 2015 +0100 @@ -24,6 +24,7 @@ import javax.lang.model.element.*; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.java.*; @@ -50,7 +51,7 @@ } public boolean hasUnexpectedValue(ProcessorContext context) { - return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getTruffleTypes().getUnexpectedValueException()); + return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getType(UnexpectedResultException.class)); } public boolean isFinal() { diff -r 144fba40c979 -r 2c669386b5d0 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Wed Dec 31 17:35:10 2014 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Fri Jan 02 14:31:51 2015 +0100 @@ -59,14 +59,25 @@ AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); List exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); List exceptionData = new ArrayList<>(); + List rewriteOnTypes = new ArrayList<>(); for (TypeMirror exceptionType : exceptionTypes) { SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { - throwsData.addError("Method must specify a throws clause with the exception type '%s'.", ElementUtils.getQualifiedName(exceptionType)); + method.addError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @%s method must specify a throws clause with the exception type '%s'.", + Specialization.class.getSimpleName(), ElementUtils.getQualifiedName(exceptionType)); } + rewriteOnTypes.add(throwsData.getJavaClass()); exceptionData.add(throwsData); } + for (TypeMirror typeMirror : method.getMethod().getThrownTypes()) { + if (!ElementUtils.canThrowType(rewriteOnTypes, typeMirror)) { + method.addError(rewriteValue, + "A checked exception '%s' is thrown but is not specified using the rewriteOn property. Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.", + ElementUtils.getQualifiedName(typeMirror)); + } + } + Collections.sort(exceptionData, new Comparator() { @Override