6943289: Project Coin: Improved Exception Handling for Java (aka 'multicatch')
Reviewed-by: jjg, darcy
This commit is contained in:
parent
3c813135d9
commit
de2b567108
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
@ -233,6 +233,11 @@ public interface Tree {
|
|||||||
*/
|
*/
|
||||||
PARAMETERIZED_TYPE(ParameterizedTypeTree.class),
|
PARAMETERIZED_TYPE(ParameterizedTypeTree.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for instances of {@link DisjointTypeTree}.
|
||||||
|
*/
|
||||||
|
DISJOINT_TYPE(DisjointTypeTree.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for instances of {@link TypeCastTree}.
|
* Used for instances of {@link TypeCastTree}.
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +96,7 @@ public interface TreeVisitor<R,P> {
|
|||||||
R visitCompilationUnit(CompilationUnitTree node, P p);
|
R visitCompilationUnit(CompilationUnitTree node, P p);
|
||||||
R visitTry(TryTree node, P p);
|
R visitTry(TryTree node, P p);
|
||||||
R visitParameterizedType(ParameterizedTypeTree node, P p);
|
R visitParameterizedType(ParameterizedTypeTree node, P p);
|
||||||
|
R visitDisjointType(DisjointTypeTree node, P p);
|
||||||
R visitArrayType(ArrayTypeTree node, P p);
|
R visitArrayType(ArrayTypeTree node, P p);
|
||||||
R visitTypeCast(TypeCastTree node, P p);
|
R visitTypeCast(TypeCastTree node, P p);
|
||||||
R visitPrimitiveType(PrimitiveTypeTree 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);
|
return defaultAction(node, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public R visitDisjointType(DisjointTypeTree node, P p) {
|
||||||
|
return defaultAction(node, p);
|
||||||
|
}
|
||||||
|
|
||||||
public R visitTypeParameter(TypeParameterTree node, P p) {
|
public R visitTypeParameter(TypeParameterTree node, P p) {
|
||||||
return defaultAction(node, p);
|
return defaultAction(node, p);
|
||||||
}
|
}
|
||||||
|
@ -354,6 +354,10 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public R visitDisjointType(DisjointTypeTree node, P p) {
|
||||||
|
return scan(node.getTypeComponents(), p);
|
||||||
|
}
|
||||||
|
|
||||||
public R visitTypeParameter(TypeParameterTree node, P p) {
|
public R visitTypeParameter(TypeParameterTree node, P p) {
|
||||||
R r = scan(node.getAnnotations(), p);
|
R r = scan(node.getAnnotations(), p);
|
||||||
r = scanAndReduce(node.getBounds(), p, r);
|
r = scanAndReduce(node.getBounds(), p, r);
|
||||||
|
@ -230,6 +230,11 @@ public class Flags {
|
|||||||
*/
|
*/
|
||||||
public static final long PROPRIETARY = 1L<<38;
|
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.
|
/** Modifier masks.
|
||||||
*/
|
*/
|
||||||
public static final int
|
public static final int
|
||||||
|
@ -125,6 +125,9 @@ public enum Source {
|
|||||||
public boolean allowDiamond() {
|
public boolean allowDiamond() {
|
||||||
return compareTo(JDK1_7) >= 0;
|
return compareTo(JDK1_7) >= 0;
|
||||||
}
|
}
|
||||||
|
public boolean allowMulticatch() {
|
||||||
|
return compareTo(JDK1_7) >= 0;
|
||||||
|
}
|
||||||
public boolean allowEnums() {
|
public boolean allowEnums() {
|
||||||
return compareTo(JDK1_5) >= 0;
|
return compareTo(JDK1_5) >= 0;
|
||||||
}
|
}
|
||||||
|
@ -988,6 +988,13 @@ public class Attr extends JCTree.Visitor {
|
|||||||
Env<AttrContext> catchEnv =
|
Env<AttrContext> catchEnv =
|
||||||
env.dup(c, env.info.dup(env.info.scope.dup()));
|
env.dup(c, env.info.dup(env.info.scope.dup()));
|
||||||
Type ctype = attribStat(c.param, catchEnv);
|
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) {
|
if (c.param.type.tsym.kind == Kinds.VAR) {
|
||||||
c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
|
c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
|
||||||
}
|
}
|
||||||
@ -2735,6 +2742,11 @@ public class Attr extends JCTree.Visitor {
|
|||||||
result = check(tree, owntype, TYP, pkind, pt);
|
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) {
|
public void visitTypeParameter(JCTypeParameter tree) {
|
||||||
TypeVar a = (TypeVar)tree.type;
|
TypeVar a = (TypeVar)tree.type;
|
||||||
Set<Type> boundSet = new HashSet<Type>();
|
Set<Type> boundSet = new HashSet<Type>();
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
package com.sun.tools.javac.comp;
|
package com.sun.tools.javac.comp;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import com.sun.tools.javac.code.*;
|
import com.sun.tools.javac.code.*;
|
||||||
import com.sun.tools.javac.tree.*;
|
import com.sun.tools.javac.tree.*;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
@ -184,6 +186,7 @@ public class Flow extends TreeScanner {
|
|||||||
private final Check chk;
|
private final Check chk;
|
||||||
private TreeMaker make;
|
private TreeMaker make;
|
||||||
private Lint lint;
|
private Lint lint;
|
||||||
|
private final boolean allowRethrowAnalysis;
|
||||||
|
|
||||||
public static Flow instance(Context context) {
|
public static Flow instance(Context context) {
|
||||||
Flow instance = context.get(flowKey);
|
Flow instance = context.get(flowKey);
|
||||||
@ -194,13 +197,14 @@ public class Flow extends TreeScanner {
|
|||||||
|
|
||||||
protected Flow(Context context) {
|
protected Flow(Context context) {
|
||||||
context.put(flowKey, this);
|
context.put(flowKey, this);
|
||||||
|
|
||||||
names = Names.instance(context);
|
names = Names.instance(context);
|
||||||
log = Log.instance(context);
|
log = Log.instance(context);
|
||||||
syms = Symtab.instance(context);
|
syms = Symtab.instance(context);
|
||||||
types = Types.instance(context);
|
types = Types.instance(context);
|
||||||
chk = Check.instance(context);
|
chk = Check.instance(context);
|
||||||
lint = Lint.instance(context);
|
lint = Lint.instance(context);
|
||||||
|
Source source = Source.instance(context);
|
||||||
|
allowRethrowAnalysis = source.allowMulticatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A flag that indicates whether the last statement could
|
/** A flag that indicates whether the last statement could
|
||||||
@ -216,6 +220,8 @@ public class Flow extends TreeScanner {
|
|||||||
*/
|
*/
|
||||||
Bits uninits;
|
Bits uninits;
|
||||||
|
|
||||||
|
HashMap<Symbol, List<Type>> multicatchTypes;
|
||||||
|
|
||||||
/** The set of variables that are definitely unassigned everywhere
|
/** The set of variables that are definitely unassigned everywhere
|
||||||
* in current try block. This variable is maintained lazily; it is
|
* in current try block. This variable is maintained lazily; it is
|
||||||
* updated only when something gets removed from uninits,
|
* 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.adr >= firstadr && trackable(sym)) {
|
||||||
if ((sym.flags() & FINAL) != 0) {
|
if ((sym.flags() & FINAL) != 0) {
|
||||||
if ((sym.flags() & PARAMETER) != 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);
|
sym);
|
||||||
|
}
|
||||||
} else if (!uninits.isMember(sym.adr)) {
|
} else if (!uninits.isMember(sym.adr)) {
|
||||||
log.error(pos,
|
log.error(pos,
|
||||||
loopPassTwo
|
loopPassTwo
|
||||||
@ -952,8 +964,14 @@ public class Flow extends TreeScanner {
|
|||||||
List<Type> caughtPrev = caught;
|
List<Type> caughtPrev = caught;
|
||||||
List<Type> thrownPrev = thrown;
|
List<Type> thrownPrev = thrown;
|
||||||
thrown = List.nil();
|
thrown = List.nil();
|
||||||
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail)
|
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
|
||||||
caught = chk.incl(l.head.param.type, caught);
|
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;
|
Bits uninitsTryPrev = uninitsTry;
|
||||||
ListBuffer<PendingExit> prevPendingExits = pendingExits;
|
ListBuffer<PendingExit> prevPendingExits = pendingExits;
|
||||||
pendingExits = new ListBuffer<PendingExit>();
|
pendingExits = new ListBuffer<PendingExit>();
|
||||||
@ -973,27 +991,39 @@ public class Flow extends TreeScanner {
|
|||||||
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
|
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
|
||||||
alive = true;
|
alive = true;
|
||||||
JCVariableDecl param = l.head.param;
|
JCVariableDecl param = l.head.param;
|
||||||
Type exc = param.type;
|
List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
|
||||||
if (chk.subset(exc, caughtInTry)) {
|
((JCTypeDisjoint)l.head.param.vartype).components :
|
||||||
log.error(l.head.pos(),
|
List.of(l.head.param.vartype);
|
||||||
"except.already.caught", exc);
|
List<Type> ctypes = List.nil();
|
||||||
} else if (!chk.isUnchecked(l.head.pos(), exc) &&
|
List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
|
||||||
exc.tsym != syms.throwableType.tsym &&
|
for (JCExpression ct : subClauses) {
|
||||||
exc.tsym != syms.exceptionType.tsym &&
|
Type exc = ct.type;
|
||||||
!chk.intersects(exc, thrownInTry)) {
|
ctypes = ctypes.append(exc);
|
||||||
log.error(l.head.pos(),
|
if (types.isSameType(exc, syms.objectType))
|
||||||
"except.never.thrown.in.try", exc);
|
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();
|
inits = initsTry.dup();
|
||||||
uninits = uninitsTry.dup();
|
uninits = uninitsTry.dup();
|
||||||
scan(param);
|
scan(param);
|
||||||
inits.incl(param.sym.adr);
|
inits.incl(param.sym.adr);
|
||||||
uninits.excl(param.sym.adr);
|
uninits.excl(param.sym.adr);
|
||||||
|
multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
|
||||||
scanStat(l.head.body);
|
scanStat(l.head.body);
|
||||||
initsEnd.andSet(inits);
|
initsEnd.andSet(inits);
|
||||||
uninitsEnd.andSet(uninits);
|
uninitsEnd.andSet(uninits);
|
||||||
nextadr = nextadrCatch;
|
nextadr = nextadrCatch;
|
||||||
|
multicatchTypes.remove(param.sym);
|
||||||
aliveEnd |= alive;
|
aliveEnd |= alive;
|
||||||
}
|
}
|
||||||
if (tree.finalizer != null) {
|
if (tree.finalizer != null) {
|
||||||
@ -1121,7 +1151,19 @@ public class Flow extends TreeScanner {
|
|||||||
|
|
||||||
public void visitThrow(JCThrow tree) {
|
public void visitThrow(JCThrow tree) {
|
||||||
scanExpr(tree.expr);
|
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();
|
markDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1308,6 +1350,7 @@ public class Flow extends TreeScanner {
|
|||||||
firstadr = 0;
|
firstadr = 0;
|
||||||
nextadr = 0;
|
nextadr = 0;
|
||||||
pendingExits = new ListBuffer<PendingExit>();
|
pendingExits = new ListBuffer<PendingExit>();
|
||||||
|
multicatchTypes = new HashMap<Symbol, List<Type>>();
|
||||||
alive = true;
|
alive = true;
|
||||||
this.thrown = this.caught = null;
|
this.thrown = this.caught = null;
|
||||||
this.classDef = null;
|
this.classDef = null;
|
||||||
|
@ -1454,20 +1454,26 @@ public class Gen extends JCTree.Visitor {
|
|||||||
int startpc, int endpc,
|
int startpc, int endpc,
|
||||||
List<Integer> gaps) {
|
List<Integer> gaps) {
|
||||||
if (startpc != endpc) {
|
if (startpc != endpc) {
|
||||||
int catchType = makeRef(tree.pos(), tree.param.type);
|
List<JCExpression> subClauses = TreeInfo.isMultiCatch(tree) ?
|
||||||
while (gaps.nonEmpty()) {
|
((JCTypeDisjoint)tree.param.vartype).components :
|
||||||
int end = gaps.head.intValue();
|
List.of(tree.param.vartype);
|
||||||
registerCatch(tree.pos(),
|
for (JCExpression subCatch : subClauses) {
|
||||||
startpc, end, code.curPc(),
|
int catchType = makeRef(tree.pos(), subCatch.type);
|
||||||
catchType);
|
List<Integer> lGaps = gaps;
|
||||||
gaps = gaps.tail;
|
while (lGaps.nonEmpty()) {
|
||||||
startpc = gaps.head.intValue();
|
int end = lGaps.head.intValue();
|
||||||
gaps = gaps.tail;
|
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;
|
VarSymbol exparam = tree.param.sym;
|
||||||
code.statBegin(tree.pos);
|
code.statBegin(tree.pos);
|
||||||
code.markStatBegin();
|
code.markStatBegin();
|
||||||
|
@ -132,6 +132,7 @@ public class JavacParser implements Parser {
|
|||||||
this.allowStaticImport = source.allowStaticImport();
|
this.allowStaticImport = source.allowStaticImport();
|
||||||
this.allowAnnotations = source.allowAnnotations();
|
this.allowAnnotations = source.allowAnnotations();
|
||||||
this.allowDiamond = source.allowDiamond();
|
this.allowDiamond = source.allowDiamond();
|
||||||
|
this.allowMulticatch = source.allowMulticatch();
|
||||||
this.allowTypeAnnotations = source.allowTypeAnnotations();
|
this.allowTypeAnnotations = source.allowTypeAnnotations();
|
||||||
this.keepDocComments = keepDocComments;
|
this.keepDocComments = keepDocComments;
|
||||||
if (keepDocComments)
|
if (keepDocComments)
|
||||||
@ -153,6 +154,10 @@ public class JavacParser implements Parser {
|
|||||||
*/
|
*/
|
||||||
boolean allowDiamond;
|
boolean allowDiamond;
|
||||||
|
|
||||||
|
/** Switch: Should multicatch clause be accepted?
|
||||||
|
*/
|
||||||
|
boolean allowMulticatch;
|
||||||
|
|
||||||
/** Switch: Should varargs be recognized?
|
/** Switch: Should varargs be recognized?
|
||||||
*/
|
*/
|
||||||
boolean allowVarargs;
|
boolean allowVarargs;
|
||||||
@ -2011,14 +2016,28 @@ public class JavacParser implements Parser {
|
|||||||
int pos = S.pos();
|
int pos = S.pos();
|
||||||
accept(CATCH);
|
accept(CATCH);
|
||||||
accept(LPAREN);
|
accept(LPAREN);
|
||||||
JCVariableDecl formal =
|
JCModifiers mods = optFinal(Flags.PARAMETER);
|
||||||
variableDeclaratorId(optFinal(Flags.PARAMETER),
|
List<JCExpression> catchTypes = catchTypes();
|
||||||
qualident());
|
JCExpression paramType = catchTypes.size() > 1 ?
|
||||||
|
toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) :
|
||||||
|
catchTypes.head;
|
||||||
|
JCVariableDecl formal = variableDeclaratorId(mods, paramType);
|
||||||
accept(RPAREN);
|
accept(RPAREN);
|
||||||
JCBlock body = block();
|
JCBlock body = block();
|
||||||
return F.at(pos).Catch(formal, body);
|
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 }
|
/** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
|
||||||
* SwitchBlockStatementGroup = SwitchLabel BlockStatements
|
* SwitchBlockStatementGroup = SwitchLabel BlockStatements
|
||||||
* SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
|
* SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
|
||||||
@ -3193,4 +3212,10 @@ public class JavacParser implements Parser {
|
|||||||
allowDiamond = true;
|
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=\
|
compiler.err.final.parameter.may.not.be.assigned=\
|
||||||
final parameter {0} 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=\
|
compiler.err.finally.without.try=\
|
||||||
''finally'' without ''try''
|
''finally'' without ''try''
|
||||||
compiler.err.foreach.not.applicable.to.type=\
|
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\
|
enums are not supported in -source {0}\n\
|
||||||
(use -source 5 or higher to enable enums)
|
(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=\
|
compiler.err.string.switch.not.supported.in.source=\
|
||||||
strings in switch are not supported in -source {0}\n\
|
strings in switch are not supported in -source {0}\n\
|
||||||
(use -source 7 or higher to enable strings in switch)
|
(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;
|
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.
|
/** Formal type parameters, of type TypeParameter.
|
||||||
*/
|
*/
|
||||||
public static final int TYPEPARAMETER = TYPEAPPLY + 1;
|
public static final int TYPEPARAMETER = TYPEDISJOINT + 1;
|
||||||
|
|
||||||
/** Type argument.
|
/** 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.
|
* A formal class parameter.
|
||||||
* @param name name
|
* @param name name
|
||||||
@ -2220,6 +2252,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
|
public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
|
||||||
public void visitTypeArray(JCArrayTypeTree that) { visitTree(that); }
|
public void visitTypeArray(JCArrayTypeTree that) { visitTree(that); }
|
||||||
public void visitTypeApply(JCTypeApply 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 visitTypeParameter(JCTypeParameter that) { visitTree(that); }
|
||||||
public void visitWildcard(JCWildcard that) { visitTree(that); }
|
public void visitWildcard(JCWildcard that) { visitTree(that); }
|
||||||
public void visitTypeBoundKind(TypeBoundKind 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) {
|
public void visitTypeParameter(JCTypeParameter tree) {
|
||||||
try {
|
try {
|
||||||
print(tree.name);
|
print(tree.name);
|
||||||
|
@ -345,6 +345,12 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
|
|||||||
return M.at(t.pos).TypeApply(clazz, arguments);
|
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) {
|
public JCTree visitArrayType(ArrayTypeTree node, P p) {
|
||||||
JCArrayTypeTree t = (JCArrayTypeTree) node;
|
JCArrayTypeTree t = (JCArrayTypeTree) node;
|
||||||
JCExpression elemtype = copy(t.elemtype, p);
|
JCExpression elemtype = copy(t.elemtype, p);
|
||||||
|
@ -118,6 +118,10 @@ public class TreeInfo {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isMultiCatch(JCCatch catchClause) {
|
||||||
|
return catchClause.param.vartype.getTag() == JCTree.TYPEDISJOINT;
|
||||||
|
}
|
||||||
|
|
||||||
/** Is statement an initializer for a synthetic field?
|
/** Is statement an initializer for a synthetic field?
|
||||||
*/
|
*/
|
||||||
public static boolean isSyntheticInit(JCTree stat) {
|
public static boolean isSyntheticInit(JCTree stat) {
|
||||||
|
@ -444,6 +444,12 @@ public class TreeMaker implements JCTree.Factory {
|
|||||||
return tree;
|
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) {
|
public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
|
||||||
return TypeParameter(name, bounds, List.<JCTypeAnnotation>nil());
|
return TypeParameter(name, bounds, List.<JCTypeAnnotation>nil());
|
||||||
}
|
}
|
||||||
|
@ -275,6 +275,10 @@ public class TreeScanner extends Visitor {
|
|||||||
scan(tree.arguments);
|
scan(tree.arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitTypeDisjoint(JCTypeDisjoint tree) {
|
||||||
|
scan(tree.components);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitTypeParameter(JCTypeParameter tree) {
|
public void visitTypeParameter(JCTypeParameter tree) {
|
||||||
scan(tree.annotations);
|
scan(tree.annotations);
|
||||||
scan(tree.bounds);
|
scan(tree.bounds);
|
||||||
|
@ -367,6 +367,11 @@ public class TreeTranslator extends JCTree.Visitor {
|
|||||||
result = tree;
|
result = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitTypeDisjoint(JCTypeDisjoint tree) {
|
||||||
|
tree.components = translate(tree.components);
|
||||||
|
result = tree;
|
||||||
|
}
|
||||||
|
|
||||||
public void visitTypeParameter(JCTypeParameter tree) {
|
public void visitTypeParameter(JCTypeParameter tree) {
|
||||||
tree.annotations = translate(tree.annotations);
|
tree.annotations = translate(tree.annotations);
|
||||||
tree.bounds = translate(tree.bounds);
|
tree.bounds = translate(tree.bounds);
|
||||||
|
28
langtools/test/tools/javac/multicatch/Neg01.java
Normal file
28
langtools/test/tools/javac/multicatch/Neg01.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* @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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/multicatch/Neg01.out
Normal file
2
langtools/test/tools/javac/multicatch/Neg01.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Neg01.java:24:19: compiler.err.except.never.thrown.in.try: Neg01.B2
|
||||||
|
1 error
|
25
langtools/test/tools/javac/multicatch/Neg02.java
Normal file
25
langtools/test/tools/javac/multicatch/Neg02.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* @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) { }
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/multicatch/Neg02.out
Normal file
2
langtools/test/tools/javac/multicatch/Neg02.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Neg02.java:23:24: compiler.err.multicatch.param.must.be.final: ex
|
||||||
|
1 error
|
27
langtools/test/tools/javac/multicatch/Neg03.java
Normal file
27
langtools/test/tools/javac/multicatch/Neg03.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* @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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/multicatch/Neg03.out
Normal file
2
langtools/test/tools/javac/multicatch/Neg03.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Neg03.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
|
||||||
|
1 error
|
31
langtools/test/tools/javac/multicatch/Neg04.java
Normal file
31
langtools/test/tools/javac/multicatch/Neg04.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* @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) {}
|
||||||
|
}
|
||||||
|
}
|
2
langtools/test/tools/javac/multicatch/Neg04.out
Normal file
2
langtools/test/tools/javac/multicatch/Neg04.out
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Neg04.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
||||||
|
1 error
|
59
langtools/test/tools/javac/multicatch/Pos01.java
Normal file
59
langtools/test/tools/javac/multicatch/Pos01.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
81
langtools/test/tools/javac/multicatch/Pos02.java
Normal file
81
langtools/test/tools/javac/multicatch/Pos02.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
langtools/test/tools/javac/multicatch/Pos03.java
Normal file
50
langtools/test/tools/javac/multicatch/Pos03.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
langtools/test/tools/javac/multicatch/Pos04.java
Normal file
92
langtools/test/tools/javac/multicatch/Pos04.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
langtools/test/tools/javac/multicatch/Pos05.java
Normal file
117
langtools/test/tools/javac/multicatch/Pos05.java
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user