提交 b1ed291b 编写于 作者: M mcimadamore

6943289: Project Coin: Improved Exception Handling for Java (aka 'multicatch')

Reviewed-by: jjg, darcy
上级 13e87dbb
/*
* Copyright 2010 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.source.tree;
import java.util.List;
/**
* A tree node for a disjoint type expression in a multicatch var declaration.
*
*
* @author Maurizio Cimadamore
*
* @since 1.7
*/
public interface DisjointTypeTree extends Tree {
List<? extends Tree> getTypeComponents();
}
\ No newline at end of file
......@@ -233,6 +233,11 @@ public interface Tree {
*/
PARAMETERIZED_TYPE(ParameterizedTypeTree.class),
/**
* Used for instances of {@link DisjointTypeTree}.
*/
DISJOINT_TYPE(DisjointTypeTree.class),
/**
* Used for instances of {@link TypeCastTree}.
*/
......
......@@ -96,6 +96,7 @@ public interface TreeVisitor<R,P> {
R visitCompilationUnit(CompilationUnitTree node, P p);
R visitTry(TryTree node, P p);
R visitParameterizedType(ParameterizedTypeTree node, P p);
R visitDisjointType(DisjointTypeTree node, P p);
R visitArrayType(ArrayTypeTree node, P p);
R visitTypeCast(TypeCastTree node, P p);
R visitPrimitiveType(PrimitiveTypeTree node, P p);
......
......@@ -228,6 +228,10 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
return defaultAction(node, p);
}
public R visitDisjointType(DisjointTypeTree node, P p) {
return defaultAction(node, p);
}
public R visitTypeParameter(TypeParameterTree node, P p) {
return defaultAction(node, p);
}
......
......@@ -354,6 +354,10 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
return r;
}
public R visitDisjointType(DisjointTypeTree node, P p) {
return scan(node.getTypeComponents(), p);
}
public R visitTypeParameter(TypeParameterTree node, P p) {
R r = scan(node.getAnnotations(), p);
r = scanAndReduce(node.getBounds(), p, r);
......
......@@ -230,6 +230,11 @@ public class Flags {
*/
public static final long PROPRIETARY = 1L<<38;
/**
* Flag that marks a disjoint var in a multi-catch clause
*/
public static final long DISJOINT = 1L<<39;
/** Modifier masks.
*/
public static final int
......
......@@ -125,6 +125,9 @@ public enum Source {
public boolean allowDiamond() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowMulticatch() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowEnums() {
return compareTo(JDK1_5) >= 0;
}
......
......@@ -988,6 +988,13 @@ public class Attr extends JCTree.Visitor {
Env<AttrContext> catchEnv =
env.dup(c, env.info.dup(env.info.scope.dup()));
Type ctype = attribStat(c.param, catchEnv);
if (TreeInfo.isMultiCatch(c)) {
//check that multi-catch parameter is marked as final
if ((c.param.sym.flags() & FINAL) == 0) {
log.error(c.param.pos(), "multicatch.param.must.be.final", c.param.sym);
}
c.param.sym.flags_field = c.param.sym.flags() | DISJOINT;
}
if (c.param.type.tsym.kind == Kinds.VAR) {
c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
}
......@@ -2735,6 +2742,11 @@ public class Attr extends JCTree.Visitor {
result = check(tree, owntype, TYP, pkind, pt);
}
public void visitTypeDisjoint(JCTypeDisjoint tree) {
List<Type> componentTypes = attribTypes(tree.components, env);
tree.type = result = check(tree, types.lub(componentTypes), TYP, pkind, pt);
}
public void visitTypeParameter(JCTypeParameter tree) {
TypeVar a = (TypeVar)tree.type;
Set<Type> boundSet = new HashSet<Type>();
......
......@@ -27,6 +27,8 @@
package com.sun.tools.javac.comp;
import java.util.HashMap;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
......@@ -184,6 +186,7 @@ public class Flow extends TreeScanner {
private final Check chk;
private TreeMaker make;
private Lint lint;
private final boolean allowRethrowAnalysis;
public static Flow instance(Context context) {
Flow instance = context.get(flowKey);
......@@ -194,13 +197,14 @@ public class Flow extends TreeScanner {
protected Flow(Context context) {
context.put(flowKey, this);
names = Names.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
types = Types.instance(context);
chk = Check.instance(context);
lint = Lint.instance(context);
Source source = Source.instance(context);
allowRethrowAnalysis = source.allowMulticatch();
}
/** A flag that indicates whether the last statement could
......@@ -216,6 +220,8 @@ public class Flow extends TreeScanner {
*/
Bits uninits;
HashMap<Symbol, List<Type>> multicatchTypes;
/** The set of variables that are definitely unassigned everywhere
* in current try block. This variable is maintained lazily; it is
* updated only when something gets removed from uninits,
......@@ -355,8 +361,14 @@ public class Flow extends TreeScanner {
if (sym.adr >= firstadr && trackable(sym)) {
if ((sym.flags() & FINAL) != 0) {
if ((sym.flags() & PARAMETER) != 0) {
log.error(pos, "final.parameter.may.not.be.assigned",
if ((sym.flags() & DISJOINT) != 0) { //multi-catch parameter
log.error(pos, "multicatch.parameter.may.not.be.assigned",
sym);
}
else {
log.error(pos, "final.parameter.may.not.be.assigned",
sym);
}
} else if (!uninits.isMember(sym.adr)) {
log.error(pos,
loopPassTwo
......@@ -952,8 +964,14 @@ public class Flow extends TreeScanner {
List<Type> caughtPrev = caught;
List<Type> thrownPrev = thrown;
thrown = List.nil();
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail)
caught = chk.incl(l.head.param.type, caught);
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
((JCTypeDisjoint)l.head.param.vartype).components :
List.of(l.head.param.vartype);
for (JCExpression ct : subClauses) {
caught = chk.incl(ct.type, caught);
}
}
Bits uninitsTryPrev = uninitsTry;
ListBuffer<PendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<PendingExit>();
......@@ -973,27 +991,39 @@ public class Flow extends TreeScanner {
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
alive = true;
JCVariableDecl param = l.head.param;
Type exc = param.type;
if (chk.subset(exc, caughtInTry)) {
log.error(l.head.pos(),
"except.already.caught", exc);
} else if (!chk.isUnchecked(l.head.pos(), exc) &&
exc.tsym != syms.throwableType.tsym &&
exc.tsym != syms.exceptionType.tsym &&
!chk.intersects(exc, thrownInTry)) {
log.error(l.head.pos(),
"except.never.thrown.in.try", exc);
List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
((JCTypeDisjoint)l.head.param.vartype).components :
List.of(l.head.param.vartype);
List<Type> ctypes = List.nil();
List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
for (JCExpression ct : subClauses) {
Type exc = ct.type;
ctypes = ctypes.append(exc);
if (types.isSameType(exc, syms.objectType))
continue;
if (chk.subset(exc, caughtInTry)) {
log.error(l.head.pos(),
"except.already.caught", exc);
} else if (!chk.isUnchecked(l.head.pos(), exc) &&
exc.tsym != syms.throwableType.tsym &&
exc.tsym != syms.exceptionType.tsym &&
!chk.intersects(exc, thrownInTry)) {
log.error(l.head.pos(),
"except.never.thrown.in.try", exc);
}
caughtInTry = chk.incl(exc, caughtInTry);
}
caughtInTry = chk.incl(exc, caughtInTry);
inits = initsTry.dup();
uninits = uninitsTry.dup();
scan(param);
inits.incl(param.sym.adr);
uninits.excl(param.sym.adr);
multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
scanStat(l.head.body);
initsEnd.andSet(inits);
uninitsEnd.andSet(uninits);
nextadr = nextadrCatch;
multicatchTypes.remove(param.sym);
aliveEnd |= alive;
}
if (tree.finalizer != null) {
......@@ -1121,7 +1151,19 @@ public class Flow extends TreeScanner {
public void visitThrow(JCThrow tree) {
scanExpr(tree.expr);
markThrown(tree, tree.expr.type);
Symbol sym = TreeInfo.symbol(tree.expr);
if (sym != null &&
sym.kind == VAR &&
(sym.flags() & FINAL) != 0 &&
multicatchTypes.get(sym) != null &&
allowRethrowAnalysis) {
for (Type t : multicatchTypes.get(sym)) {
markThrown(tree, t);
}
}
else {
markThrown(tree, tree.expr.type);
}
markDead();
}
......@@ -1308,6 +1350,7 @@ public class Flow extends TreeScanner {
firstadr = 0;
nextadr = 0;
pendingExits = new ListBuffer<PendingExit>();
multicatchTypes = new HashMap<Symbol, List<Type>>();
alive = true;
this.thrown = this.caught = null;
this.classDef = null;
......
......@@ -1454,20 +1454,26 @@ public class Gen extends JCTree.Visitor {
int startpc, int endpc,
List<Integer> gaps) {
if (startpc != endpc) {
int catchType = makeRef(tree.pos(), tree.param.type);
while (gaps.nonEmpty()) {
int end = gaps.head.intValue();
registerCatch(tree.pos(),
startpc, end, code.curPc(),
catchType);
gaps = gaps.tail;
startpc = gaps.head.intValue();
gaps = gaps.tail;
List<JCExpression> subClauses = TreeInfo.isMultiCatch(tree) ?
((JCTypeDisjoint)tree.param.vartype).components :
List.of(tree.param.vartype);
for (JCExpression subCatch : subClauses) {
int catchType = makeRef(tree.pos(), subCatch.type);
List<Integer> lGaps = gaps;
while (lGaps.nonEmpty()) {
int end = lGaps.head.intValue();
registerCatch(tree.pos(),
startpc, end, code.curPc(),
catchType);
lGaps = lGaps.tail;
startpc = lGaps.head.intValue();
lGaps = lGaps.tail;
}
if (startpc < endpc)
registerCatch(tree.pos(),
startpc, endpc, code.curPc(),
catchType);
}
if (startpc < endpc)
registerCatch(tree.pos(),
startpc, endpc, code.curPc(),
catchType);
VarSymbol exparam = tree.param.sym;
code.statBegin(tree.pos);
code.markStatBegin();
......
......@@ -132,6 +132,7 @@ public class JavacParser implements Parser {
this.allowStaticImport = source.allowStaticImport();
this.allowAnnotations = source.allowAnnotations();
this.allowDiamond = source.allowDiamond();
this.allowMulticatch = source.allowMulticatch();
this.allowTypeAnnotations = source.allowTypeAnnotations();
this.keepDocComments = keepDocComments;
if (keepDocComments)
......@@ -153,6 +154,10 @@ public class JavacParser implements Parser {
*/
boolean allowDiamond;
/** Switch: Should multicatch clause be accepted?
*/
boolean allowMulticatch;
/** Switch: Should varargs be recognized?
*/
boolean allowVarargs;
......@@ -2011,14 +2016,28 @@ public class JavacParser implements Parser {
int pos = S.pos();
accept(CATCH);
accept(LPAREN);
JCVariableDecl formal =
variableDeclaratorId(optFinal(Flags.PARAMETER),
qualident());
JCModifiers mods = optFinal(Flags.PARAMETER);
List<JCExpression> catchTypes = catchTypes();
JCExpression paramType = catchTypes.size() > 1 ?
toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) :
catchTypes.head;
JCVariableDecl formal = variableDeclaratorId(mods, paramType);
accept(RPAREN);
JCBlock body = block();
return F.at(pos).Catch(formal, body);
}
List<JCExpression> catchTypes() {
ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
catchTypes.add(parseType());
while (S.token() == BAR) {
checkMulticatch();
S.nextToken();
catchTypes.add(qualident());
}
return catchTypes.toList();
}
/** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
* SwitchBlockStatementGroup = SwitchLabel BlockStatements
* SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
......@@ -3193,4 +3212,10 @@ public class JavacParser implements Parser {
allowDiamond = true;
}
}
void checkMulticatch() {
if (!allowMulticatch) {
log.error(S.pos(), "multicatch.not.supported.in.source", source.name);
allowMulticatch = true;
}
}
}
......@@ -172,6 +172,10 @@ compiler.err.except.never.thrown.in.try=\
compiler.err.final.parameter.may.not.be.assigned=\
final parameter {0} may not be assigned
compiler.err.multicatch.parameter.may.not.be.assigned=\
multi-catch parameter {0} may not be assigned
compiler.err.multicatch.param.must.be.final=\
multi-catch parameter {0} must be final
compiler.err.finally.without.try=\
''finally'' without ''try''
compiler.err.foreach.not.applicable.to.type=\
......@@ -1235,6 +1239,10 @@ compiler.err.enums.not.supported.in.source=\
enums are not supported in -source {0}\n\
(use -source 5 or higher to enable enums)
compiler.err.multicatch.not.supported.in.source=\
multi-catch statement is not supported in -source {0}\n\
(use -source 7 or higher to enable multi-catch statement)
compiler.err.string.switch.not.supported.in.source=\
strings in switch are not supported in -source {0}\n\
(use -source 7 or higher to enable strings in switch)
......
......@@ -236,9 +236,13 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
public static final int TYPEAPPLY = TYPEARRAY + 1;
/** Disjunctive types, of type TypeDisjoint.
*/
public static final int TYPEDISJOINT = TYPEAPPLY + 1;
/** Formal type parameters, of type TypeParameter.
*/
public static final int TYPEPARAMETER = TYPEAPPLY + 1;
public static final int TYPEPARAMETER = TYPEDISJOINT + 1;
/** Type argument.
*/
......@@ -1862,6 +1866,34 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
}
/**
* A disjoint type, T1 | T2 | ... Tn (used in multicatch statements)
*/
public static class JCTypeDisjoint extends JCExpression implements DisjointTypeTree {
public List<JCExpression> components;
protected JCTypeDisjoint(List<JCExpression> components) {
this.components = components;
}
@Override
public void accept(Visitor v) { v.visitTypeDisjoint(this); }
public Kind getKind() { return Kind.DISJOINT_TYPE; }
public List<JCExpression> getTypeComponents() {
return components;
}
@Override
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitDisjointType(this, d);
}
@Override
public int getTag() {
return TYPEDISJOINT;
}
}
/**
* A formal class parameter.
* @param name name
......@@ -2220,6 +2252,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
public void visitTypeArray(JCArrayTypeTree that) { visitTree(that); }
public void visitTypeApply(JCTypeApply that) { visitTree(that); }
public void visitTypeDisjoint(JCTypeDisjoint that) { visitTree(that); }
public void visitTypeParameter(JCTypeParameter that) { visitTree(that); }
public void visitWildcard(JCWildcard that) { visitTree(that); }
public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); }
......
......@@ -1182,6 +1182,14 @@ public class Pretty extends JCTree.Visitor {
}
}
public void visitTypeDisjoint(JCTypeDisjoint tree) {
try {
printExprs(tree.components, " | ");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitTypeParameter(JCTypeParameter tree) {
try {
print(tree.name);
......
......@@ -345,6 +345,12 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
return M.at(t.pos).TypeApply(clazz, arguments);
}
public JCTree visitDisjointType(DisjointTypeTree node, P p) {
JCTypeDisjoint t = (JCTypeDisjoint) node;
List<JCExpression> components = copy(t.components, p);
return M.at(t.pos).TypeDisjoint(components);
}
public JCTree visitArrayType(ArrayTypeTree node, P p) {
JCArrayTypeTree t = (JCArrayTypeTree) node;
JCExpression elemtype = copy(t.elemtype, p);
......
......@@ -118,6 +118,10 @@ public class TreeInfo {
return false;
}
public static boolean isMultiCatch(JCCatch catchClause) {
return catchClause.param.vartype.getTag() == JCTree.TYPEDISJOINT;
}
/** Is statement an initializer for a synthetic field?
*/
public static boolean isSyntheticInit(JCTree stat) {
......
......@@ -444,6 +444,12 @@ public class TreeMaker implements JCTree.Factory {
return tree;
}
public JCTypeDisjoint TypeDisjoint(List<JCExpression> components) {
JCTypeDisjoint tree = new JCTypeDisjoint(components);
tree.pos = pos;
return tree;
}
public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
return TypeParameter(name, bounds, List.<JCTypeAnnotation>nil());
}
......
......@@ -275,6 +275,10 @@ public class TreeScanner extends Visitor {
scan(tree.arguments);
}
public void visitTypeDisjoint(JCTypeDisjoint tree) {
scan(tree.components);
}
public void visitTypeParameter(JCTypeParameter tree) {
scan(tree.annotations);
scan(tree.bounds);
......
......@@ -367,6 +367,11 @@ public class TreeTranslator extends JCTree.Visitor {
result = tree;
}
public void visitTypeDisjoint(JCTypeDisjoint tree) {
tree.components = translate(tree.components);
result = tree;
}
public void visitTypeParameter(JCTypeParameter tree) {
tree.annotations = translate(tree.annotations);
tree.bounds = translate(tree.bounds);
......
/*
* @test /nodynamiccopyright/
* @bug 6943289
*
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
* @author darcy
* @compile/fail/ref=Neg01.out -XDrawDiagnostics Neg01.java
* @compile -source 6 -XDrawDiagnostics Neg01.java
*
*/
class Neg01 {
static class A extends Exception {}
static class B1 extends A {}
static class B2 extends A {}
class Test {
void m() throws A {
try {
throw new B1();
} catch (final A ex1) {
try {
throw ex1; // used to throw A, now throws B1!
} catch (B2 ex2) { }//unreachable
}
}
}
}
Neg01.java:24:19: compiler.err.except.never.thrown.in.try: Neg01.B2
1 error
/*
* @test /nodynamiccopyright/
* @bug 6943289
*
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
* @author mcimadamore
* @compile/fail/ref=Neg02.out -XDrawDiagnostics Neg02.java
*
*/
class Neg02 {
static class A extends Exception {}
static class B extends Exception {}
void m() {
try {
if (true) {
throw new A();
}
else {
throw new B();
}
} catch (A | B ex) { }
}
}
Neg02.java:23:24: compiler.err.multicatch.param.must.be.final: ex
1 error
/*
* @test /nodynamiccopyright/
* @bug 6943289
*
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
* @author mcimadamore
* @compile/fail/ref=Neg03.out -XDrawDiagnostics Neg03.java
*
*/
class Neg03 {
static class A extends Exception {}
static class B extends Exception {}
void m() {
try {
if (true) {
throw new A();
}
else {
throw new B();
}
} catch (final A | B ex) {
ex = new B();
}
}
}
Neg03.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
1 error
/*
* @test /nodynamiccopyright/
* @bug 6943289
*
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
* @author mcimadamore
* @compile/fail/ref=Neg04.out -XDrawDiagnostics Neg04.java
*
*/
class Neg04 {
static class A extends Exception {}
static class B extends Exception {}
void test() throws B {
try {
if (true) {
throw new A();
} else if (false) {
throw new B();
} else {
throw (Throwable)new Exception();
}
}
catch (A e) {}
catch (final Exception e) {
throw e;
}
catch (Throwable t) {}
}
}
Neg04.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
1 error
/*
* Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6943289
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
*
*/
public class Pos01 {
static class A extends Exception {}
static class B extends Exception {}
static int caughtExceptions = 0;
static void test(boolean b) {
try {
if (b) {
throw new A();
}
else {
throw new B();
}
}
catch (final A | B ex) {
caughtExceptions++;
}
}
public static void main(String[] args) {
test(true);
test(false);
if (caughtExceptions != 2) {
throw new AssertionError("Exception handler called " + caughtExceptions + "times");
}
}
}
/*
* Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6943289
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
*
*/
public class Pos02 {
static class A extends Exception {}
static class B extends Exception {}
static class C extends Exception {}
static class C1 extends C {}
static class C2 extends C {}
enum ExceptionKind {
A,
B,
C1,
C2
}
static int caughtExceptions = 0;
static int caughtRethrownExceptions = 0;
static void test(ExceptionKind ekind) throws A, C1 {
try {
switch (ekind) {
case A : throw new A();
case B : throw new B();
case C1: throw new C1();
case C2 : throw new C2();
}
}
catch (final C2 | B ex) {
caughtExceptions++;
}
catch (final C | A ex) {
caughtExceptions++;
throw ex;
}
}
public static void main(String[] args) {
for (ExceptionKind ekind : ExceptionKind.values()) {
try {
test(ekind);
}
catch (final C1 | A ex) {
caughtRethrownExceptions++;
}
}
if (caughtExceptions != 4 && caughtRethrownExceptions == 2) {
throw new AssertionError("Exception handler called " + caughtExceptions + "times" +
" rethrown handler called " + caughtRethrownExceptions + "times");
}
}
}
/*
* Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6943289
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
* @compile Pos03.java
*/
class Pos03 {
static class A extends Exception { public void m() {}; public Object f;}
static class B1 extends A {}
static class B2 extends A {}
void m() {
try {
if (true) {
throw new B1();
}
else {
throw new B2();
}
} catch (final B1 | B2 ex) {
ex.m();
System.out.println(ex.f);
}
}
}
/*
* Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6943289
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
*/
import java.lang.annotation.*;
public class Pos04 {
enum ExceptionKind {
A(1),
B(2),
C(1);
int expectedValue;
ExceptionKind(int expectedValue) {
this.expectedValue = expectedValue;
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface CatchNumber {
int value();
}
@CatchNumber(1)
static class A extends Exception { }
@CatchNumber(2)
static class B extends Exception { }
@CatchNumber(1)
static class C extends Exception { }
static int sum = 0;
public static void main(String[] args) {
for (ExceptionKind ekind : ExceptionKind.values()) {
test(ekind);
}
if (sum != 4) {
throw new Error("bad checksum - expected:4, found:" + sum);
}
}
public static void test(ExceptionKind ekind) {
try {
switch(ekind) {
case A: throw new A();
case B: throw new B();
case C: throw new C();
}
} catch(final A | C ex) {// Catch number 1
CatchNumber catchNumber = ex.getClass().getAnnotation(CatchNumber.class);
if (catchNumber == null || catchNumber.value() != ekind.expectedValue) {
throw new Error("was expecting 1 - got " + catchNumber);
}
sum += catchNumber.value();
} catch (final B ex) { // Catch number 2
CatchNumber catchNumber = ex.getClass().getAnnotation(CatchNumber.class);
if (catchNumber == null || catchNumber.value() != ekind.expectedValue) {
throw new Error("was expecting 2 - got " + catchNumber);
}
sum += catchNumber.value();
}
}
}
/*
* Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6943289
* @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
* @run main Pos05
*/
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.Code_attribute.Exception_data;
import com.sun.tools.classfile.Method;
import java.io.*;
public class Pos05 {
static class Pos05sub {
class A extends Exception {}
class B extends Exception {}
class C extends Exception {}
void test(boolean b1, boolean b2) {
try {
if (b1) {
throw new A();
}
else if (b2) {
throw new B();
}
else {
throw new C();
}
}
catch (final A | B | C ex) {
System.out.println("Exception caught");
}
}
}
static final int TYPES_IN_MULTICATCH = 3;
static final String SUBTEST_NAME = Pos05sub.class.getName() + ".class";
static final String TEST_METHOD_NAME = "test";
public static void main(String... args) throws Exception {
new Pos05().run();
}
public void run() throws Exception {
String workDir = System.getProperty("test.classes");
File compiledTest = new File(workDir, SUBTEST_NAME);
verifyMulticatchExceptionRanges(compiledTest);
}
void verifyMulticatchExceptionRanges(File f) {
System.err.println("verify: " + f);
try {
int count = 0;
ClassFile cf = ClassFile.read(f);
Method testMethod = null;
for (Method m : cf.methods) {
if (m.getName(cf.constant_pool).equals(TEST_METHOD_NAME)) {
testMethod = m;
break;
}
}
if (testMethod == null) {
throw new Error("Test method not found");
}
Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code);
if (testMethod == null) {
throw new Error("Code attribute for test() method not found");
}
Exception_data firstExceptionTable = null;
for (int i = 0 ; i < ea.exception_table_langth; i++) {
if (firstExceptionTable == null) {
firstExceptionTable = ea.exception_table[i];
}
if (ea.exception_table[i].handler_pc != firstExceptionTable.handler_pc ||
ea.exception_table[i].start_pc != firstExceptionTable.start_pc ||
ea.exception_table[i].end_pc != firstExceptionTable.end_pc) {
throw new Error("Multiple overlapping catch clause found in generated code");
}
count++;
}
if (count != TYPES_IN_MULTICATCH) {
throw new Error("Wrong number of exception data found: " + count);
}
} catch (Exception e) {
e.printStackTrace();
throw new Error("error reading " + f +": " + e);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册