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),
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
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