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

Mon, 03 May 2010 17:12:59 -0700

author
mcimadamore
date
Mon, 03 May 2010 17:12:59 -0700
changeset 550
a6f2911a7c55
parent 549
c399da99fa16
child 551
1cb2b5acc291
child 560
ebf09be0222c

6943289: Project Coin: Improved Exception Handling for Java (aka 'multicatch')
Reviewed-by: jjg, darcy

src/share/classes/com/sun/source/tree/DisjointTypeTree.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/source/tree/Tree.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/source/tree/TreeVisitor.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/source/util/SimpleTreeVisitor.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/source/util/TreeScanner.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Flags.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Source.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Flow.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/jvm/Gen.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/JavacParser.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/resources/compiler.properties file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/JCTree.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/Pretty.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeCopier.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeInfo.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeMaker.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeScanner.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg01.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg01.out file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg02.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg02.out file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg03.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg03.out file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg04.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Neg04.out file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Pos01.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Pos02.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Pos03.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Pos04.java file | annotate | diff | comparison | revisions
test/tools/javac/multicatch/Pos05.java file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/source/tree/DisjointTypeTree.java	Mon May 03 17:12:59 2010 -0700
     1.3 @@ -0,0 +1,40 @@
     1.4 +/*
     1.5 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Sun designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Sun in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.26 + * have any questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.source.tree;
    1.30 +
    1.31 +import java.util.List;
    1.32 +
    1.33 +/**
    1.34 + * A tree node for a disjoint type expression in a multicatch var declaration.
    1.35 + *
    1.36 + *
    1.37 + * @author Maurizio Cimadamore
    1.38 + *
    1.39 + * @since 1.7
    1.40 + */
    1.41 +public interface DisjointTypeTree extends Tree {
    1.42 +    List<? extends Tree> getTypeComponents();
    1.43 +}
    1.44 \ No newline at end of file
     2.1 --- a/src/share/classes/com/sun/source/tree/Tree.java	Sun May 02 15:55:02 2010 -0700
     2.2 +++ b/src/share/classes/com/sun/source/tree/Tree.java	Mon May 03 17:12:59 2010 -0700
     2.3 @@ -234,6 +234,11 @@
     2.4          PARAMETERIZED_TYPE(ParameterizedTypeTree.class),
     2.5  
     2.6          /**
     2.7 +         * Used for instances of {@link DisjointTypeTree}.
     2.8 +         */
     2.9 +        DISJOINT_TYPE(DisjointTypeTree.class),
    2.10 +
    2.11 +        /**
    2.12           * Used for instances of {@link TypeCastTree}.
    2.13           */
    2.14          TYPE_CAST(TypeCastTree.class),
     3.1 --- a/src/share/classes/com/sun/source/tree/TreeVisitor.java	Sun May 02 15:55:02 2010 -0700
     3.2 +++ b/src/share/classes/com/sun/source/tree/TreeVisitor.java	Mon May 03 17:12:59 2010 -0700
     3.3 @@ -96,6 +96,7 @@
     3.4      R visitCompilationUnit(CompilationUnitTree node, P p);
     3.5      R visitTry(TryTree node, P p);
     3.6      R visitParameterizedType(ParameterizedTypeTree node, P p);
     3.7 +    R visitDisjointType(DisjointTypeTree node, P p);
     3.8      R visitArrayType(ArrayTypeTree node, P p);
     3.9      R visitTypeCast(TypeCastTree node, P p);
    3.10      R visitPrimitiveType(PrimitiveTypeTree node, P p);
     4.1 --- a/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Sun May 02 15:55:02 2010 -0700
     4.2 +++ b/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Mon May 03 17:12:59 2010 -0700
     4.3 @@ -228,6 +228,10 @@
     4.4          return defaultAction(node, p);
     4.5      }
     4.6  
     4.7 +    public R visitDisjointType(DisjointTypeTree node, P p) {
     4.8 +        return defaultAction(node, p);
     4.9 +    }
    4.10 +
    4.11      public R visitTypeParameter(TypeParameterTree node, P p) {
    4.12          return defaultAction(node, p);
    4.13      }
     5.1 --- a/src/share/classes/com/sun/source/util/TreeScanner.java	Sun May 02 15:55:02 2010 -0700
     5.2 +++ b/src/share/classes/com/sun/source/util/TreeScanner.java	Mon May 03 17:12:59 2010 -0700
     5.3 @@ -354,6 +354,10 @@
     5.4          return r;
     5.5      }
     5.6  
     5.7 +    public R visitDisjointType(DisjointTypeTree node, P p) {
     5.8 +        return scan(node.getTypeComponents(), p);
     5.9 +    }
    5.10 +
    5.11      public R visitTypeParameter(TypeParameterTree node, P p) {
    5.12          R r = scan(node.getAnnotations(), p);
    5.13          r = scanAndReduce(node.getBounds(), p, r);
     6.1 --- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Sun May 02 15:55:02 2010 -0700
     6.2 +++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Mon May 03 17:12:59 2010 -0700
     6.3 @@ -230,6 +230,11 @@
     6.4       */
     6.5      public static final long PROPRIETARY = 1L<<38;
     6.6  
     6.7 +    /**
     6.8 +     * Flag that marks a disjoint var in a multi-catch clause
     6.9 +     */
    6.10 +    public static final long DISJOINT = 1L<<39;
    6.11 +
    6.12      /** Modifier masks.
    6.13       */
    6.14      public static final int
     7.1 --- a/src/share/classes/com/sun/tools/javac/code/Source.java	Sun May 02 15:55:02 2010 -0700
     7.2 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java	Mon May 03 17:12:59 2010 -0700
     7.3 @@ -125,6 +125,9 @@
     7.4      public boolean allowDiamond() {
     7.5          return compareTo(JDK1_7) >= 0;
     7.6      }
     7.7 +    public boolean allowMulticatch() {
     7.8 +        return compareTo(JDK1_7) >= 0;
     7.9 +    }
    7.10      public boolean allowEnums() {
    7.11          return compareTo(JDK1_5) >= 0;
    7.12      }
     8.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Sun May 02 15:55:02 2010 -0700
     8.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon May 03 17:12:59 2010 -0700
     8.3 @@ -988,6 +988,13 @@
     8.4              Env<AttrContext> catchEnv =
     8.5                  env.dup(c, env.info.dup(env.info.scope.dup()));
     8.6              Type ctype = attribStat(c.param, catchEnv);
     8.7 +            if (TreeInfo.isMultiCatch(c)) {
     8.8 +                //check that multi-catch parameter is marked as final
     8.9 +                if ((c.param.sym.flags() & FINAL) == 0) {
    8.10 +                    log.error(c.param.pos(), "multicatch.param.must.be.final", c.param.sym);
    8.11 +                }
    8.12 +                c.param.sym.flags_field = c.param.sym.flags() | DISJOINT;
    8.13 +            }
    8.14              if (c.param.type.tsym.kind == Kinds.VAR) {
    8.15                  c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
    8.16              }
    8.17 @@ -2735,6 +2742,11 @@
    8.18          result = check(tree, owntype, TYP, pkind, pt);
    8.19      }
    8.20  
    8.21 +    public void visitTypeDisjoint(JCTypeDisjoint tree) {
    8.22 +        List<Type> componentTypes = attribTypes(tree.components, env);
    8.23 +        tree.type = result = check(tree, types.lub(componentTypes), TYP, pkind, pt);
    8.24 +    }
    8.25 +
    8.26      public void visitTypeParameter(JCTypeParameter tree) {
    8.27          TypeVar a = (TypeVar)tree.type;
    8.28          Set<Type> boundSet = new HashSet<Type>();
     9.1 --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Sun May 02 15:55:02 2010 -0700
     9.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Mon May 03 17:12:59 2010 -0700
     9.3 @@ -27,6 +27,8 @@
     9.4  
     9.5  package com.sun.tools.javac.comp;
     9.6  
     9.7 +import java.util.HashMap;
     9.8 +
     9.9  import com.sun.tools.javac.code.*;
    9.10  import com.sun.tools.javac.tree.*;
    9.11  import com.sun.tools.javac.util.*;
    9.12 @@ -184,6 +186,7 @@
    9.13      private final Check chk;
    9.14      private       TreeMaker make;
    9.15      private       Lint lint;
    9.16 +    private final boolean allowRethrowAnalysis;
    9.17  
    9.18      public static Flow instance(Context context) {
    9.19          Flow instance = context.get(flowKey);
    9.20 @@ -194,13 +197,14 @@
    9.21  
    9.22      protected Flow(Context context) {
    9.23          context.put(flowKey, this);
    9.24 -
    9.25          names = Names.instance(context);
    9.26          log = Log.instance(context);
    9.27          syms = Symtab.instance(context);
    9.28          types = Types.instance(context);
    9.29          chk = Check.instance(context);
    9.30          lint = Lint.instance(context);
    9.31 +        Source source = Source.instance(context);
    9.32 +        allowRethrowAnalysis = source.allowMulticatch();
    9.33      }
    9.34  
    9.35      /** A flag that indicates whether the last statement could
    9.36 @@ -216,6 +220,8 @@
    9.37       */
    9.38      Bits uninits;
    9.39  
    9.40 +    HashMap<Symbol, List<Type>> multicatchTypes;
    9.41 +
    9.42      /** The set of variables that are definitely unassigned everywhere
    9.43       *  in current try block. This variable is maintained lazily; it is
    9.44       *  updated only when something gets removed from uninits,
    9.45 @@ -355,8 +361,14 @@
    9.46          if (sym.adr >= firstadr && trackable(sym)) {
    9.47              if ((sym.flags() & FINAL) != 0) {
    9.48                  if ((sym.flags() & PARAMETER) != 0) {
    9.49 -                    log.error(pos, "final.parameter.may.not.be.assigned",
    9.50 +                    if ((sym.flags() & DISJOINT) != 0) { //multi-catch parameter
    9.51 +                        log.error(pos, "multicatch.parameter.may.not.be.assigned",
    9.52 +                                  sym);
    9.53 +                    }
    9.54 +                    else {
    9.55 +                        log.error(pos, "final.parameter.may.not.be.assigned",
    9.56                                sym);
    9.57 +                    }
    9.58                  } else if (!uninits.isMember(sym.adr)) {
    9.59                      log.error(pos,
    9.60                                loopPassTwo
    9.61 @@ -952,8 +964,14 @@
    9.62          List<Type> caughtPrev = caught;
    9.63          List<Type> thrownPrev = thrown;
    9.64          thrown = List.nil();
    9.65 -        for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail)
    9.66 -            caught = chk.incl(l.head.param.type, caught);
    9.67 +        for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
    9.68 +            List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
    9.69 +                    ((JCTypeDisjoint)l.head.param.vartype).components :
    9.70 +                    List.of(l.head.param.vartype);
    9.71 +            for (JCExpression ct : subClauses) {
    9.72 +                caught = chk.incl(ct.type, caught);
    9.73 +            }
    9.74 +        }
    9.75          Bits uninitsTryPrev = uninitsTry;
    9.76          ListBuffer<PendingExit> prevPendingExits = pendingExits;
    9.77          pendingExits = new ListBuffer<PendingExit>();
    9.78 @@ -973,27 +991,39 @@
    9.79          for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
    9.80              alive = true;
    9.81              JCVariableDecl param = l.head.param;
    9.82 -            Type exc = param.type;
    9.83 -            if (chk.subset(exc, caughtInTry)) {
    9.84 -                log.error(l.head.pos(),
    9.85 -                          "except.already.caught", exc);
    9.86 -            } else if (!chk.isUnchecked(l.head.pos(), exc) &&
    9.87 -                       exc.tsym != syms.throwableType.tsym &&
    9.88 -                       exc.tsym != syms.exceptionType.tsym &&
    9.89 -                       !chk.intersects(exc, thrownInTry)) {
    9.90 -                log.error(l.head.pos(),
    9.91 -                          "except.never.thrown.in.try", exc);
    9.92 +            List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
    9.93 +                    ((JCTypeDisjoint)l.head.param.vartype).components :
    9.94 +                    List.of(l.head.param.vartype);
    9.95 +            List<Type> ctypes = List.nil();
    9.96 +            List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
    9.97 +            for (JCExpression ct : subClauses) {
    9.98 +                Type exc = ct.type;
    9.99 +                ctypes = ctypes.append(exc);
   9.100 +                if (types.isSameType(exc, syms.objectType))
   9.101 +                    continue;
   9.102 +                if (chk.subset(exc, caughtInTry)) {
   9.103 +                    log.error(l.head.pos(),
   9.104 +                              "except.already.caught", exc);
   9.105 +                } else if (!chk.isUnchecked(l.head.pos(), exc) &&
   9.106 +                           exc.tsym != syms.throwableType.tsym &&
   9.107 +                           exc.tsym != syms.exceptionType.tsym &&
   9.108 +                           !chk.intersects(exc, thrownInTry)) {
   9.109 +                    log.error(l.head.pos(),
   9.110 +                              "except.never.thrown.in.try", exc);
   9.111 +                }
   9.112 +                caughtInTry = chk.incl(exc, caughtInTry);
   9.113              }
   9.114 -            caughtInTry = chk.incl(exc, caughtInTry);
   9.115              inits = initsTry.dup();
   9.116              uninits = uninitsTry.dup();
   9.117              scan(param);
   9.118              inits.incl(param.sym.adr);
   9.119              uninits.excl(param.sym.adr);
   9.120 +            multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
   9.121              scanStat(l.head.body);
   9.122              initsEnd.andSet(inits);
   9.123              uninitsEnd.andSet(uninits);
   9.124              nextadr = nextadrCatch;
   9.125 +            multicatchTypes.remove(param.sym);
   9.126              aliveEnd |= alive;
   9.127          }
   9.128          if (tree.finalizer != null) {
   9.129 @@ -1121,7 +1151,19 @@
   9.130  
   9.131      public void visitThrow(JCThrow tree) {
   9.132          scanExpr(tree.expr);
   9.133 -        markThrown(tree, tree.expr.type);
   9.134 +        Symbol sym = TreeInfo.symbol(tree.expr);
   9.135 +        if (sym != null &&
   9.136 +            sym.kind == VAR &&
   9.137 +            (sym.flags() & FINAL) != 0 &&
   9.138 +            multicatchTypes.get(sym) != null &&
   9.139 +            allowRethrowAnalysis) {
   9.140 +            for (Type t : multicatchTypes.get(sym)) {
   9.141 +                markThrown(tree, t);
   9.142 +            }
   9.143 +        }
   9.144 +        else {
   9.145 +            markThrown(tree, tree.expr.type);
   9.146 +        }
   9.147          markDead();
   9.148      }
   9.149  
   9.150 @@ -1308,6 +1350,7 @@
   9.151              firstadr = 0;
   9.152              nextadr = 0;
   9.153              pendingExits = new ListBuffer<PendingExit>();
   9.154 +            multicatchTypes = new HashMap<Symbol, List<Type>>();
   9.155              alive = true;
   9.156              this.thrown = this.caught = null;
   9.157              this.classDef = null;
    10.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Sun May 02 15:55:02 2010 -0700
    10.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon May 03 17:12:59 2010 -0700
    10.3 @@ -1454,20 +1454,26 @@
    10.4                        int startpc, int endpc,
    10.5                        List<Integer> gaps) {
    10.6              if (startpc != endpc) {
    10.7 -                int catchType = makeRef(tree.pos(), tree.param.type);
    10.8 -                while (gaps.nonEmpty()) {
    10.9 -                    int end = gaps.head.intValue();
   10.10 -                    registerCatch(tree.pos(),
   10.11 -                                  startpc,  end, code.curPc(),
   10.12 -                                  catchType);
   10.13 -                    gaps = gaps.tail;
   10.14 -                    startpc = gaps.head.intValue();
   10.15 -                    gaps = gaps.tail;
   10.16 +                List<JCExpression> subClauses = TreeInfo.isMultiCatch(tree) ?
   10.17 +                    ((JCTypeDisjoint)tree.param.vartype).components :
   10.18 +                    List.of(tree.param.vartype);
   10.19 +                for (JCExpression subCatch : subClauses) {
   10.20 +                    int catchType = makeRef(tree.pos(), subCatch.type);
   10.21 +                    List<Integer> lGaps = gaps;
   10.22 +                    while (lGaps.nonEmpty()) {
   10.23 +                        int end = lGaps.head.intValue();
   10.24 +                        registerCatch(tree.pos(),
   10.25 +                                      startpc,  end, code.curPc(),
   10.26 +                                      catchType);
   10.27 +                        lGaps = lGaps.tail;
   10.28 +                        startpc = lGaps.head.intValue();
   10.29 +                        lGaps = lGaps.tail;
   10.30 +                    }
   10.31 +                    if (startpc < endpc)
   10.32 +                        registerCatch(tree.pos(),
   10.33 +                                      startpc, endpc, code.curPc(),
   10.34 +                                      catchType);
   10.35                  }
   10.36 -                if (startpc < endpc)
   10.37 -                    registerCatch(tree.pos(),
   10.38 -                                  startpc, endpc, code.curPc(),
   10.39 -                                  catchType);
   10.40                  VarSymbol exparam = tree.param.sym;
   10.41                  code.statBegin(tree.pos);
   10.42                  code.markStatBegin();
    11.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Sun May 02 15:55:02 2010 -0700
    11.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon May 03 17:12:59 2010 -0700
    11.3 @@ -132,6 +132,7 @@
    11.4          this.allowStaticImport = source.allowStaticImport();
    11.5          this.allowAnnotations = source.allowAnnotations();
    11.6          this.allowDiamond = source.allowDiamond();
    11.7 +        this.allowMulticatch = source.allowMulticatch();
    11.8          this.allowTypeAnnotations = source.allowTypeAnnotations();
    11.9          this.keepDocComments = keepDocComments;
   11.10          if (keepDocComments)
   11.11 @@ -153,6 +154,10 @@
   11.12       */
   11.13      boolean allowDiamond;
   11.14  
   11.15 +    /** Switch: Should multicatch clause be accepted?
   11.16 +     */
   11.17 +    boolean allowMulticatch;
   11.18 +
   11.19      /** Switch: Should varargs be recognized?
   11.20       */
   11.21      boolean allowVarargs;
   11.22 @@ -2011,14 +2016,28 @@
   11.23          int pos = S.pos();
   11.24          accept(CATCH);
   11.25          accept(LPAREN);
   11.26 -        JCVariableDecl formal =
   11.27 -            variableDeclaratorId(optFinal(Flags.PARAMETER),
   11.28 -                                 qualident());
   11.29 +        JCModifiers mods = optFinal(Flags.PARAMETER);
   11.30 +        List<JCExpression> catchTypes = catchTypes();
   11.31 +        JCExpression paramType = catchTypes.size() > 1 ?
   11.32 +                toP(F.at(catchTypes.head.getStartPosition()).TypeDisjoint(catchTypes)) :
   11.33 +                catchTypes.head;
   11.34 +        JCVariableDecl formal = variableDeclaratorId(mods, paramType);
   11.35          accept(RPAREN);
   11.36          JCBlock body = block();
   11.37          return F.at(pos).Catch(formal, body);
   11.38      }
   11.39  
   11.40 +    List<JCExpression> catchTypes() {
   11.41 +        ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
   11.42 +        catchTypes.add(parseType());
   11.43 +        while (S.token() == BAR) {
   11.44 +            checkMulticatch();
   11.45 +            S.nextToken();
   11.46 +            catchTypes.add(qualident());
   11.47 +        }
   11.48 +        return catchTypes.toList();
   11.49 +    }
   11.50 +
   11.51      /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
   11.52       *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
   11.53       *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
   11.54 @@ -3193,4 +3212,10 @@
   11.55              allowDiamond = true;
   11.56          }
   11.57      }
   11.58 +    void checkMulticatch() {
   11.59 +        if (!allowMulticatch) {
   11.60 +            log.error(S.pos(), "multicatch.not.supported.in.source", source.name);
   11.61 +            allowMulticatch = true;
   11.62 +            }
   11.63 +    }
   11.64  }
    12.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Sun May 02 15:55:02 2010 -0700
    12.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon May 03 17:12:59 2010 -0700
    12.3 @@ -172,6 +172,10 @@
    12.4  
    12.5  compiler.err.final.parameter.may.not.be.assigned=\
    12.6      final parameter {0} may not be assigned
    12.7 +compiler.err.multicatch.parameter.may.not.be.assigned=\
    12.8 +    multi-catch parameter {0} may not be assigned
    12.9 +compiler.err.multicatch.param.must.be.final=\
   12.10 +    multi-catch parameter {0} must be final
   12.11  compiler.err.finally.without.try=\
   12.12      ''finally'' without ''try''
   12.13  compiler.err.foreach.not.applicable.to.type=\
   12.14 @@ -1235,6 +1239,10 @@
   12.15      enums are not supported in -source {0}\n\
   12.16  (use -source 5 or higher to enable enums)
   12.17  
   12.18 +compiler.err.multicatch.not.supported.in.source=\
   12.19 +    multi-catch statement is not supported in -source {0}\n\
   12.20 +(use -source 7 or higher to enable multi-catch statement)
   12.21 +
   12.22  compiler.err.string.switch.not.supported.in.source=\
   12.23      strings in switch are not supported in -source {0}\n\
   12.24  (use -source 7 or higher to enable strings in switch)
    13.1 --- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Sun May 02 15:55:02 2010 -0700
    13.2 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon May 03 17:12:59 2010 -0700
    13.3 @@ -236,9 +236,13 @@
    13.4       */
    13.5      public static final int TYPEAPPLY = TYPEARRAY + 1;
    13.6  
    13.7 +    /** Disjunctive types, of type TypeDisjoint.
    13.8 +     */
    13.9 +    public static final int TYPEDISJOINT = TYPEAPPLY + 1;
   13.10 +
   13.11      /** Formal type parameters, of type TypeParameter.
   13.12       */
   13.13 -    public static final int TYPEPARAMETER = TYPEAPPLY + 1;
   13.14 +    public static final int TYPEPARAMETER = TYPEDISJOINT + 1;
   13.15  
   13.16      /** Type argument.
   13.17       */
   13.18 @@ -1863,6 +1867,34 @@
   13.19      }
   13.20  
   13.21      /**
   13.22 +     * A disjoint type, T1 | T2 | ... Tn (used in multicatch statements)
   13.23 +     */
   13.24 +    public static class JCTypeDisjoint extends JCExpression implements DisjointTypeTree {
   13.25 +
   13.26 +        public List<JCExpression> components;
   13.27 +
   13.28 +        protected JCTypeDisjoint(List<JCExpression> components) {
   13.29 +            this.components = components;
   13.30 +        }
   13.31 +        @Override
   13.32 +        public void accept(Visitor v) { v.visitTypeDisjoint(this); }
   13.33 +
   13.34 +        public Kind getKind() { return Kind.DISJOINT_TYPE; }
   13.35 +
   13.36 +        public List<JCExpression> getTypeComponents() {
   13.37 +            return components;
   13.38 +        }
   13.39 +        @Override
   13.40 +        public <R,D> R accept(TreeVisitor<R,D> v, D d) {
   13.41 +            return v.visitDisjointType(this, d);
   13.42 +        }
   13.43 +        @Override
   13.44 +        public int getTag() {
   13.45 +            return TYPEDISJOINT;
   13.46 +        }
   13.47 +    }
   13.48 +
   13.49 +    /**
   13.50       * A formal class parameter.
   13.51       * @param name name
   13.52       * @param bounds bounds
   13.53 @@ -2220,6 +2252,7 @@
   13.54          public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
   13.55          public void visitTypeArray(JCArrayTypeTree that)     { visitTree(that); }
   13.56          public void visitTypeApply(JCTypeApply that)         { visitTree(that); }
   13.57 +        public void visitTypeDisjoint(JCTypeDisjoint that)   { visitTree(that); }
   13.58          public void visitTypeParameter(JCTypeParameter that) { visitTree(that); }
   13.59          public void visitWildcard(JCWildcard that)           { visitTree(that); }
   13.60          public void visitTypeBoundKind(TypeBoundKind that)   { visitTree(that); }
    14.1 --- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Sun May 02 15:55:02 2010 -0700
    14.2 +++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon May 03 17:12:59 2010 -0700
    14.3 @@ -1182,6 +1182,14 @@
    14.4          }
    14.5      }
    14.6  
    14.7 +    public void visitTypeDisjoint(JCTypeDisjoint tree) {
    14.8 +        try {
    14.9 +            printExprs(tree.components, " | ");
   14.10 +        } catch (IOException e) {
   14.11 +            throw new UncheckedIOException(e);
   14.12 +        }
   14.13 +    }
   14.14 +
   14.15      public void visitTypeParameter(JCTypeParameter tree) {
   14.16          try {
   14.17              print(tree.name);
    15.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Sun May 02 15:55:02 2010 -0700
    15.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Mon May 03 17:12:59 2010 -0700
    15.3 @@ -345,6 +345,12 @@
    15.4          return M.at(t.pos).TypeApply(clazz, arguments);
    15.5      }
    15.6  
    15.7 +    public JCTree visitDisjointType(DisjointTypeTree node, P p) {
    15.8 +        JCTypeDisjoint t = (JCTypeDisjoint) node;
    15.9 +        List<JCExpression> components = copy(t.components, p);
   15.10 +        return M.at(t.pos).TypeDisjoint(components);
   15.11 +    }
   15.12 +
   15.13      public JCTree visitArrayType(ArrayTypeTree node, P p) {
   15.14          JCArrayTypeTree t = (JCArrayTypeTree) node;
   15.15          JCExpression elemtype = copy(t.elemtype, p);
    16.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Sun May 02 15:55:02 2010 -0700
    16.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon May 03 17:12:59 2010 -0700
    16.3 @@ -118,6 +118,10 @@
    16.4          return false;
    16.5      }
    16.6  
    16.7 +    public static boolean isMultiCatch(JCCatch catchClause) {
    16.8 +        return catchClause.param.vartype.getTag() == JCTree.TYPEDISJOINT;
    16.9 +    }
   16.10 +
   16.11      /** Is statement an initializer for a synthetic field?
   16.12       */
   16.13      public static boolean isSyntheticInit(JCTree stat) {
    17.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Sun May 02 15:55:02 2010 -0700
    17.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon May 03 17:12:59 2010 -0700
    17.3 @@ -444,6 +444,12 @@
    17.4          return tree;
    17.5      }
    17.6  
    17.7 +    public JCTypeDisjoint TypeDisjoint(List<JCExpression> components) {
    17.8 +        JCTypeDisjoint tree = new JCTypeDisjoint(components);
    17.9 +        tree.pos = pos;
   17.10 +        return tree;
   17.11 +    }
   17.12 +
   17.13      public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
   17.14          return TypeParameter(name, bounds, List.<JCTypeAnnotation>nil());
   17.15      }
    18.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Sun May 02 15:55:02 2010 -0700
    18.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Mon May 03 17:12:59 2010 -0700
    18.3 @@ -275,6 +275,10 @@
    18.4          scan(tree.arguments);
    18.5      }
    18.6  
    18.7 +    public void visitTypeDisjoint(JCTypeDisjoint tree) {
    18.8 +        scan(tree.components);
    18.9 +    }
   18.10 +
   18.11      public void visitTypeParameter(JCTypeParameter tree) {
   18.12          scan(tree.annotations);
   18.13          scan(tree.bounds);
    19.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Sun May 02 15:55:02 2010 -0700
    19.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Mon May 03 17:12:59 2010 -0700
    19.3 @@ -367,6 +367,11 @@
    19.4          result = tree;
    19.5      }
    19.6  
    19.7 +    public void visitTypeDisjoint(JCTypeDisjoint tree) {
    19.8 +        tree.components = translate(tree.components);
    19.9 +        result = tree;
   19.10 +    }
   19.11 +
   19.12      public void visitTypeParameter(JCTypeParameter tree) {
   19.13          tree.annotations = translate(tree.annotations);
   19.14          tree.bounds = translate(tree.bounds);
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/tools/javac/multicatch/Neg01.java	Mon May 03 17:12:59 2010 -0700
    20.3 @@ -0,0 +1,28 @@
    20.4 +/*
    20.5 + * @test /nodynamiccopyright/
    20.6 + * @bug 6943289
    20.7 + *
    20.8 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
    20.9 + * @author darcy
   20.10 + * @compile/fail/ref=Neg01.out -XDrawDiagnostics Neg01.java
   20.11 + * @compile -source 6 -XDrawDiagnostics Neg01.java
   20.12 + *
   20.13 + */
   20.14 +
   20.15 +class Neg01 {
   20.16 +    static class A extends Exception {}
   20.17 +    static class B1 extends A {}
   20.18 +    static class B2 extends A {}
   20.19 +
   20.20 +    class Test {
   20.21 +        void m() throws A {
   20.22 +            try {
   20.23 +                throw new B1();
   20.24 +            } catch (final A ex1) {
   20.25 +                try {
   20.26 +                    throw ex1; // used to throw A, now throws B1!
   20.27 +                } catch (B2 ex2) { }//unreachable
   20.28 +            }
   20.29 +        }
   20.30 +    }
   20.31 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/tools/javac/multicatch/Neg01.out	Mon May 03 17:12:59 2010 -0700
    21.3 @@ -0,0 +1,2 @@
    21.4 +Neg01.java:24:19: compiler.err.except.never.thrown.in.try: Neg01.B2
    21.5 +1 error
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/tools/javac/multicatch/Neg02.java	Mon May 03 17:12:59 2010 -0700
    22.3 @@ -0,0 +1,25 @@
    22.4 +/*
    22.5 + * @test /nodynamiccopyright/
    22.6 + * @bug 6943289
    22.7 + *
    22.8 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
    22.9 + * @author mcimadamore
   22.10 + * @compile/fail/ref=Neg02.out -XDrawDiagnostics Neg02.java
   22.11 + *
   22.12 + */
   22.13 +
   22.14 +class Neg02 {
   22.15 +    static class A extends Exception {}
   22.16 +    static class B extends Exception {}
   22.17 +
   22.18 +    void m() {
   22.19 +        try {
   22.20 +            if (true) {
   22.21 +                throw new A();
   22.22 +            }
   22.23 +            else {
   22.24 +                throw new B();
   22.25 +            }
   22.26 +        } catch (A | B ex) {  }
   22.27 +    }
   22.28 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/test/tools/javac/multicatch/Neg02.out	Mon May 03 17:12:59 2010 -0700
    23.3 @@ -0,0 +1,2 @@
    23.4 +Neg02.java:23:24: compiler.err.multicatch.param.must.be.final: ex
    23.5 +1 error
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/test/tools/javac/multicatch/Neg03.java	Mon May 03 17:12:59 2010 -0700
    24.3 @@ -0,0 +1,27 @@
    24.4 +/*
    24.5 + * @test /nodynamiccopyright/
    24.6 + * @bug 6943289
    24.7 + *
    24.8 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
    24.9 + * @author mcimadamore
   24.10 + * @compile/fail/ref=Neg03.out -XDrawDiagnostics Neg03.java
   24.11 + *
   24.12 + */
   24.13 +
   24.14 +class Neg03 {
   24.15 +    static class A extends Exception {}
   24.16 +    static class B extends Exception {}
   24.17 +
   24.18 +    void m() {
   24.19 +        try {
   24.20 +            if (true) {
   24.21 +                throw new A();
   24.22 +            }
   24.23 +            else {
   24.24 +                throw new B();
   24.25 +            }
   24.26 +        } catch (final A | B ex) {
   24.27 +            ex = new B();
   24.28 +        }
   24.29 +    }
   24.30 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/test/tools/javac/multicatch/Neg03.out	Mon May 03 17:12:59 2010 -0700
    25.3 @@ -0,0 +1,2 @@
    25.4 +Neg03.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
    25.5 +1 error
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/test/tools/javac/multicatch/Neg04.java	Mon May 03 17:12:59 2010 -0700
    26.3 @@ -0,0 +1,31 @@
    26.4 +/*
    26.5 + * @test /nodynamiccopyright/
    26.6 + * @bug 6943289
    26.7 + *
    26.8 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
    26.9 + * @author mcimadamore
   26.10 + * @compile/fail/ref=Neg04.out -XDrawDiagnostics Neg04.java
   26.11 + *
   26.12 + */
   26.13 +
   26.14 +class Neg04 {
   26.15 +    static class A extends Exception {}
   26.16 +    static class B extends Exception {}
   26.17 +
   26.18 +    void test() throws B {
   26.19 +        try {
   26.20 +            if (true) {
   26.21 +                throw new A();
   26.22 +            } else if (false) {
   26.23 +                throw new B();
   26.24 +            } else {
   26.25 +                throw (Throwable)new Exception();
   26.26 +            }
   26.27 +        }
   26.28 +        catch (A e) {}
   26.29 +        catch (final Exception e) {
   26.30 +            throw e;
   26.31 +        }
   26.32 +        catch (Throwable t) {}
   26.33 +    }
   26.34 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/test/tools/javac/multicatch/Neg04.out	Mon May 03 17:12:59 2010 -0700
    27.3 @@ -0,0 +1,2 @@
    27.4 +Neg04.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
    27.5 +1 error
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/test/tools/javac/multicatch/Pos01.java	Mon May 03 17:12:59 2010 -0700
    28.3 @@ -0,0 +1,59 @@
    28.4 +/*
    28.5 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
    28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.7 + *
    28.8 + * This code is free software; you can redistribute it and/or modify it
    28.9 + * under the terms of the GNU General Public License version 2 only, as
   28.10 + * published by the Free Software Foundation.
   28.11 + *
   28.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.15 + * version 2 for more details (a copy is included in the LICENSE file that
   28.16 + * accompanied this code).
   28.17 + *
   28.18 + * You should have received a copy of the GNU General Public License version
   28.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.21 + *
   28.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   28.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   28.24 + * have any questions.
   28.25 + */
   28.26 +
   28.27 +/*
   28.28 + * @test
   28.29 + * @bug 6943289
   28.30 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
   28.31 + *
   28.32 + */
   28.33 +
   28.34 +public class Pos01 {
   28.35 +
   28.36 +    static class A extends Exception {}
   28.37 +    static class B extends Exception {}
   28.38 +
   28.39 +    static int caughtExceptions = 0;
   28.40 +
   28.41 +    static void test(boolean b) {
   28.42 +        try {
   28.43 +            if (b) {
   28.44 +                throw new A();
   28.45 +            }
   28.46 +            else {
   28.47 +                throw new B();
   28.48 +            }
   28.49 +        }
   28.50 +        catch (final A | B ex) {
   28.51 +            caughtExceptions++;
   28.52 +        }
   28.53 +    }
   28.54 +
   28.55 +    public static void main(String[] args) {
   28.56 +        test(true);
   28.57 +        test(false);
   28.58 +        if (caughtExceptions != 2) {
   28.59 +            throw new AssertionError("Exception handler called " + caughtExceptions + "times");
   28.60 +        }
   28.61 +    }
   28.62 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/tools/javac/multicatch/Pos02.java	Mon May 03 17:12:59 2010 -0700
    29.3 @@ -0,0 +1,81 @@
    29.4 +/*
    29.5 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.
   29.11 + *
   29.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.15 + * version 2 for more details (a copy is included in the LICENSE file that
   29.16 + * accompanied this code).
   29.17 + *
   29.18 + * You should have received a copy of the GNU General Public License version
   29.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.21 + *
   29.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   29.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   29.24 + * have any questions.
   29.25 + */
   29.26 +
   29.27 +/*
   29.28 + * @test
   29.29 + * @bug 6943289
   29.30 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
   29.31 + *
   29.32 + */
   29.33 +
   29.34 +public class Pos02 {
   29.35 +
   29.36 +    static class A extends Exception {}
   29.37 +    static class B extends Exception {}
   29.38 +    static class C extends Exception {}
   29.39 +    static class C1 extends C {}
   29.40 +    static class C2 extends C {}
   29.41 +
   29.42 +    enum ExceptionKind {
   29.43 +        A,
   29.44 +        B,
   29.45 +        C1,
   29.46 +        C2
   29.47 +    }
   29.48 +
   29.49 +    static int caughtExceptions = 0;
   29.50 +    static int caughtRethrownExceptions = 0;
   29.51 +
   29.52 +    static void test(ExceptionKind ekind) throws A, C1 {
   29.53 +        try {
   29.54 +            switch (ekind) {
   29.55 +                case A : throw new A();
   29.56 +                case B : throw new B();
   29.57 +                case C1: throw new C1();
   29.58 +                case C2 : throw new C2();
   29.59 +            }
   29.60 +        }
   29.61 +        catch (final C2 | B ex) {
   29.62 +            caughtExceptions++;
   29.63 +        }
   29.64 +        catch (final C | A ex) {
   29.65 +            caughtExceptions++;
   29.66 +            throw ex;
   29.67 +        }
   29.68 +    }
   29.69 +
   29.70 +    public static void main(String[] args) {
   29.71 +        for (ExceptionKind ekind : ExceptionKind.values()) {
   29.72 +            try {
   29.73 +                test(ekind);
   29.74 +            }
   29.75 +            catch (final C1 | A ex) {
   29.76 +                caughtRethrownExceptions++;
   29.77 +            }
   29.78 +        }
   29.79 +        if (caughtExceptions != 4 && caughtRethrownExceptions == 2) {
   29.80 +            throw new AssertionError("Exception handler called " + caughtExceptions + "times" +
   29.81 +                                     " rethrown handler called " + caughtRethrownExceptions + "times");
   29.82 +        }
   29.83 +    }
   29.84 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/test/tools/javac/multicatch/Pos03.java	Mon May 03 17:12:59 2010 -0700
    30.3 @@ -0,0 +1,50 @@
    30.4 +/*
    30.5 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
    30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 + *
    30.8 + * This code is free software; you can redistribute it and/or modify it
    30.9 + * under the terms of the GNU General Public License version 2 only, as
   30.10 + * published by the Free Software Foundation.
   30.11 + *
   30.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.15 + * version 2 for more details (a copy is included in the LICENSE file that
   30.16 + * accompanied this code).
   30.17 + *
   30.18 + * You should have received a copy of the GNU General Public License version
   30.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.21 + *
   30.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   30.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   30.24 + * have any questions.
   30.25 + */
   30.26 +
   30.27 +/*
   30.28 + * @test
   30.29 + * @bug 6943289
   30.30 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
   30.31 + * @compile Pos03.java
   30.32 + */
   30.33 +
   30.34 +class Pos03 {
   30.35 +
   30.36 +    static class A extends Exception { public void m() {}; public Object f;}
   30.37 +    static class B1 extends A {}
   30.38 +    static class B2 extends A {}
   30.39 +
   30.40 +    void m() {
   30.41 +        try {
   30.42 +            if (true) {
   30.43 +                throw new B1();
   30.44 +            }
   30.45 +            else {
   30.46 +                throw new B2();
   30.47 +            }
   30.48 +        } catch (final B1 | B2 ex) {
   30.49 +            ex.m();
   30.50 +            System.out.println(ex.f);
   30.51 +        }
   30.52 +    }
   30.53 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/test/tools/javac/multicatch/Pos04.java	Mon May 03 17:12:59 2010 -0700
    31.3 @@ -0,0 +1,92 @@
    31.4 +/*
    31.5 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.
   31.11 + *
   31.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.15 + * version 2 for more details (a copy is included in the LICENSE file that
   31.16 + * accompanied this code).
   31.17 + *
   31.18 + * You should have received a copy of the GNU General Public License version
   31.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.21 + *
   31.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   31.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   31.24 + * have any questions.
   31.25 + */
   31.26 +
   31.27 +/*
   31.28 + * @test
   31.29 + * @bug 6943289
   31.30 + * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
   31.31 + */
   31.32 +
   31.33 +import java.lang.annotation.*;
   31.34 +
   31.35 +public class Pos04 {
   31.36 +
   31.37 +    enum ExceptionKind {
   31.38 +        A(1),
   31.39 +        B(2),
   31.40 +        C(1);
   31.41 +
   31.42 +        int expectedValue;
   31.43 +
   31.44 +        ExceptionKind(int expectedValue) {
   31.45 +            this.expectedValue = expectedValue;
   31.46 +        }
   31.47 +    }
   31.48 +
   31.49 +    @Retention(RetentionPolicy.RUNTIME)
   31.50 +    @interface CatchNumber {
   31.51 +       int value();
   31.52 +    }
   31.53 +
   31.54 +    @CatchNumber(1)
   31.55 +    static class A extends Exception { }
   31.56 +
   31.57 +    @CatchNumber(2)
   31.58 +    static class B extends Exception { }
   31.59 +
   31.60 +    @CatchNumber(1)
   31.61 +    static class C extends Exception { }
   31.62 +
   31.63 +    static int sum = 0;
   31.64 +
   31.65 +    public static void main(String[] args) {
   31.66 +        for (ExceptionKind ekind : ExceptionKind.values()) {
   31.67 +            test(ekind);
   31.68 +        }
   31.69 +        if (sum != 4) {
   31.70 +            throw new Error("bad checksum - expected:4, found:" + sum);
   31.71 +        }
   31.72 +    }
   31.73 +
   31.74 +    public static void test(ExceptionKind ekind) {
   31.75 +        try {
   31.76 +            switch(ekind) {
   31.77 +                case A: throw new A();
   31.78 +                case B: throw new B();
   31.79 +                case C: throw new C();
   31.80 +            }
   31.81 +        } catch(final A | C ex) {// Catch number 1
   31.82 +            CatchNumber catchNumber = ex.getClass().getAnnotation(CatchNumber.class);
   31.83 +            if (catchNumber == null || catchNumber.value() != ekind.expectedValue) {
   31.84 +                throw new Error("was expecting 1 - got " + catchNumber);
   31.85 +            }
   31.86 +            sum += catchNumber.value();
   31.87 +        } catch (final B ex) { // Catch number 2
   31.88 +            CatchNumber catchNumber = ex.getClass().getAnnotation(CatchNumber.class);
   31.89 +            if (catchNumber == null || catchNumber.value() != ekind.expectedValue) {
   31.90 +                throw new Error("was expecting 2 - got " + catchNumber);
   31.91 +            }
   31.92 +            sum += catchNumber.value();
   31.93 +        }
   31.94 +    }
   31.95 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/test/tools/javac/multicatch/Pos05.java	Mon May 03 17:12:59 2010 -0700
    32.3 @@ -0,0 +1,117 @@
    32.4 +/*
    32.5 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.
   32.11 + *
   32.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.15 + * version 2 for more details (a copy is included in the LICENSE file that
   32.16 + * accompanied this code).
   32.17 + *
   32.18 + * You should have received a copy of the GNU General Public License version
   32.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.21 + *
   32.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   32.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   32.24 + * have any questions.
   32.25 + */
   32.26 +
   32.27 +/*
   32.28 + * @test
   32.29 + * @bug 6943289
   32.30 + * @summary  Project Coin: Improved Exception Handling for Java (aka 'multicatch')
   32.31 + * @run main Pos05
   32.32 + */
   32.33 +
   32.34 +import com.sun.tools.classfile.Attribute;
   32.35 +import com.sun.tools.classfile.ClassFile;
   32.36 +import com.sun.tools.classfile.Code_attribute;
   32.37 +import com.sun.tools.classfile.Code_attribute.Exception_data;
   32.38 +import com.sun.tools.classfile.Method;
   32.39 +import java.io.*;
   32.40 +
   32.41 +public class Pos05 {
   32.42 +
   32.43 +    static class Pos05sub {
   32.44 +
   32.45 +        class A extends Exception {}
   32.46 +        class B extends Exception {}
   32.47 +        class C extends Exception {}
   32.48 +
   32.49 +        void test(boolean b1, boolean b2) {
   32.50 +            try {
   32.51 +                if (b1) {
   32.52 +                    throw new A();
   32.53 +                }
   32.54 +                else if (b2) {
   32.55 +                    throw new B();
   32.56 +                }
   32.57 +                else {
   32.58 +                    throw new C();
   32.59 +                }
   32.60 +            }
   32.61 +            catch (final A | B | C ex) {
   32.62 +                System.out.println("Exception caught");
   32.63 +            }
   32.64 +        }
   32.65 +    }
   32.66 +
   32.67 +    static final int TYPES_IN_MULTICATCH = 3;
   32.68 +    static final String SUBTEST_NAME = Pos05sub.class.getName() + ".class";
   32.69 +    static final String TEST_METHOD_NAME = "test";
   32.70 +
   32.71 +    public static void main(String... args) throws Exception {
   32.72 +        new Pos05().run();
   32.73 +    }
   32.74 +
   32.75 +    public void run() throws Exception {
   32.76 +        String workDir = System.getProperty("test.classes");
   32.77 +        File compiledTest = new File(workDir, SUBTEST_NAME);
   32.78 +        verifyMulticatchExceptionRanges(compiledTest);
   32.79 +    }
   32.80 +
   32.81 +    void verifyMulticatchExceptionRanges(File f) {
   32.82 +        System.err.println("verify: " + f);
   32.83 +        try {
   32.84 +            int count = 0;
   32.85 +            ClassFile cf = ClassFile.read(f);
   32.86 +            Method testMethod = null;
   32.87 +            for (Method m : cf.methods) {
   32.88 +                if (m.getName(cf.constant_pool).equals(TEST_METHOD_NAME)) {
   32.89 +                    testMethod = m;
   32.90 +                    break;
   32.91 +                }
   32.92 +            }
   32.93 +            if (testMethod == null) {
   32.94 +                throw new Error("Test method not found");
   32.95 +            }
   32.96 +            Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code);
   32.97 +            if (testMethod == null) {
   32.98 +                throw new Error("Code attribute for test() method not found");
   32.99 +            }
  32.100 +            Exception_data firstExceptionTable = null;
  32.101 +            for (int i = 0 ; i < ea.exception_table_langth; i++) {
  32.102 +                if (firstExceptionTable == null) {
  32.103 +                    firstExceptionTable = ea.exception_table[i];
  32.104 +                }
  32.105 +                if (ea.exception_table[i].handler_pc != firstExceptionTable.handler_pc ||
  32.106 +                        ea.exception_table[i].start_pc != firstExceptionTable.start_pc ||
  32.107 +                        ea.exception_table[i].end_pc != firstExceptionTable.end_pc) {
  32.108 +                    throw new Error("Multiple overlapping catch clause found in generated code");
  32.109 +                }
  32.110 +                count++;
  32.111 +            }
  32.112 +            if (count != TYPES_IN_MULTICATCH) {
  32.113 +                throw new Error("Wrong number of exception data found: " + count);
  32.114 +            }
  32.115 +        } catch (Exception e) {
  32.116 +            e.printStackTrace();
  32.117 +            throw new Error("error reading " + f +": " + e);
  32.118 +        }
  32.119 +    }
  32.120 +}

mercurial