changeset 787:f2048d9c666e

6993963: Project Coin: Use precise exception analysis for effectively final catch parameters Summary: More precise rethrow analysis should be extended to effectively-final exception parameters. Multicatch parameters should be made implicitly final. Reviewed-by: jjg, darcy
author mcimadamore
date Thu, 04 Nov 2010 12:57:48 +0000
parents fadc6d3e63f4
children e9e41c88b03e
files src/share/classes/com/sun/tools/javac/code/Flags.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Flow.java src/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/diags/examples/MulticatchMustBeFinal.java test/tools/javac/multicatch/Neg01eff_final.java test/tools/javac/multicatch/Neg01eff_final.out test/tools/javac/multicatch/Neg02.java test/tools/javac/multicatch/Neg02.out test/tools/javac/multicatch/Neg02eff_final.java test/tools/javac/multicatch/Neg02eff_final.out test/tools/javac/multicatch/Neg03.java test/tools/javac/multicatch/Neg03.out test/tools/javac/multicatch/Neg04eff_final.java test/tools/javac/multicatch/Neg04eff_final.out test/tools/javac/multicatch/Neg05.java test/tools/javac/multicatch/Neg05.out test/tools/javac/multicatch/Pos06.java test/tools/javac/multicatch/Pos07.java test/tools/javac/multicatch/model/Check.java test/tools/javac/multicatch/model/Member.java test/tools/javac/multicatch/model/Model01.java test/tools/javac/multicatch/model/ModelChecker.java
diffstat 23 files changed, 437 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Tue Nov 02 12:01:35 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Thu Nov 04 12:57:48 2010 +0000
@@ -247,6 +247,11 @@
      */
     public static final long OVERRIDE_BRIDGE = 1L<<41;
 
+    /**
+     * Flag that marks an 'effectively final' local variable
+     */
+    public static final long EFFECTIVELY_FINAL = 1L<<42;
+
     /** Modifier masks.
      */
     public static final int
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Nov 02 12:01:35 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Nov 04 12:57:48 2010 +0000
@@ -256,6 +256,8 @@
             } else {
                 log.error(pos, "cant.assign.val.to.final.var", v);
             }
+        } else if ((v.flags() & EFFECTIVELY_FINAL) != 0) {
+            v.flags_field &= ~EFFECTIVELY_FINAL;
         }
     }
 
@@ -799,6 +801,7 @@
                 memberEnter.memberEnter(tree, env);
                 annotate.flush();
             }
+            tree.sym.flags_field |= EFFECTIVELY_FINAL;
         }
 
         VarSymbol v = tree.sym;
@@ -1061,11 +1064,8 @@
                 localEnv.dup(c, localEnv.info.dup(localEnv.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() | DISJUNCTION;
+                //multi-catch parameter is implicitly marked as final
+                c.param.sym.flags_field |= FINAL | DISJUNCTION;
             }
             if (c.param.sym.kind == Kinds.VAR) {
                 c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Tue Nov 02 12:01:35 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Nov 04 12:57:48 2010 +0000
@@ -226,7 +226,7 @@
      */
     Bits uninits;
 
-    HashMap<Symbol, List<Type>> multicatchTypes;
+    HashMap<Symbol, List<Type>> preciseRethrowTypes;
 
     /** The set of variables that are definitely unassigned everywhere
      *  in current try block. This variable is maintained lazily; it is
@@ -332,7 +332,7 @@
         if (!chk.isUnchecked(tree.pos(), exc)) {
             if (!chk.isHandled(exc, caught))
                 pendingExits.append(new PendingExit(tree, exc));
-            thrown = chk.incl(exc, thrown);
+                thrown = chk.incl(exc, thrown);
         }
     }
 
@@ -1077,12 +1077,12 @@
             scan(param);
             inits.incl(param.sym.adr);
             uninits.excl(param.sym.adr);
-            multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
+            preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
             scanStat(l.head.body);
             initsEnd.andSet(inits);
             uninitsEnd.andSet(uninits);
             nextadr = nextadrCatch;
-            multicatchTypes.remove(param.sym);
+            preciseRethrowTypes.remove(param.sym);
             aliveEnd |= alive;
         }
         if (tree.finalizer != null) {
@@ -1215,10 +1215,10 @@
         Symbol sym = TreeInfo.symbol(tree.expr);
         if (sym != null &&
             sym.kind == VAR &&
-            (sym.flags() & FINAL) != 0 &&
-            multicatchTypes.get(sym) != null &&
+            (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
+            preciseRethrowTypes.get(sym) != null &&
             allowRethrowAnalysis) {
-            for (Type t : multicatchTypes.get(sym)) {
+            for (Type t : preciseRethrowTypes.get(sym)) {
                 markThrown(tree, t);
             }
         }
@@ -1422,7 +1422,7 @@
             firstadr = 0;
             nextadr = 0;
             pendingExits = new ListBuffer<PendingExit>();
-            multicatchTypes = new HashMap<Symbol, List<Type>>();
+            preciseRethrowTypes = new HashMap<Symbol, List<Type>>();
             alive = true;
             this.thrown = this.caught = null;
             this.classDef = null;
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Nov 02 12:01:35 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Nov 04 12:57:48 2010 +0000
@@ -187,8 +187,6 @@
     automatic resource {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=\
--- a/test/tools/javac/diags/examples/MulticatchMustBeFinal.java	Tue Nov 02 12:01:35 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.multicatch.param.must.be.final
-
-class MulticatchMustBeFinal {
-    void e1() throws NullPointerException { }
-    void e2() throws IllegalArgumentException { }
-
-    void m() {
-        try {
-            e1();
-            e2();
-        } catch (NullPointerException | IllegalArgumentException e) {
-            e.printStackTrace();
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg01eff_final.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,28 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author darcy
+ * @compile/fail/ref=Neg01eff_final.out -XDrawDiagnostics Neg01eff_final.java
+ * @compile -source 6 -XDrawDiagnostics Neg01eff_final.java
+ *
+ */
+
+class Neg01eff_final {
+    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 (A ex1) {
+                try {
+                    throw ex1; // used to throw A, now throws B1!
+                } catch (B2 ex2) { }//unreachable
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg01eff_final.out	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg01eff_final.java:24:19: compiler.err.except.never.thrown.in.try: Neg01eff_final.B2
+1 error
--- a/test/tools/javac/multicatch/Neg02.java	Tue Nov 02 12:01:35 2010 +0000
+++ b/test/tools/javac/multicatch/Neg02.java	Thu Nov 04 12:57:48 2010 +0000
@@ -20,6 +20,8 @@
             else {
                 throw new B();
             }
-        } catch (A | B ex) {  }
+        } catch (final A | B ex) {
+            ex = new B();
+        }
     }
 }
--- a/test/tools/javac/multicatch/Neg02.out	Tue Nov 02 12:01:35 2010 +0000
+++ b/test/tools/javac/multicatch/Neg02.out	Thu Nov 04 12:57:48 2010 +0000
@@ -1,2 +1,2 @@
-Neg02.java:23:24: compiler.err.multicatch.param.must.be.final: ex
+Neg02.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg02eff_final.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289 6993963
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author mcimadamore
+ * @compile/fail/ref=Neg02eff_final.out -XDrawDiagnostics Neg02eff_final.java
+ *
+ */
+
+class Neg02eff_final {
+    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) {
+            ex = new B();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg02eff_final.out	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg02eff_final.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
+1 error
--- a/test/tools/javac/multicatch/Neg03.java	Tue Nov 02 12:01:35 2010 +0000
+++ b/test/tools/javac/multicatch/Neg03.java	Thu Nov 04 12:57:48 2010 +0000
@@ -9,19 +9,22 @@
  */
 
 class Neg03 {
-    static class A extends Exception {}
-    static class B extends Exception {}
 
-    void m() {
+    static class A extends Exception { public void m() {}; public Object f;}
+    static class B1 extends A {}
+    static class B2 extends A {}
+
+    void m() throws B1, B2 {
         try {
             if (true) {
-                throw new A();
+                throw new B1();
             }
             else {
-                throw new B();
+                throw new B2();
             }
-        } catch (final A | B ex) {
-            ex = new B();
+        } catch (Exception ex) {
+            ex = new B2(); //effectively final analysis disabled!
+            throw ex;
         }
     }
 }
--- a/test/tools/javac/multicatch/Neg03.out	Tue Nov 02 12:01:35 2010 +0000
+++ b/test/tools/javac/multicatch/Neg03.out	Thu Nov 04 12:57:48 2010 +0000
@@ -1,2 +1,2 @@
-Neg03.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
+Neg03.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg04eff_final.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,31 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author mcimadamore
+ * @compile/fail/ref=Neg04eff_final.out -XDrawDiagnostics Neg04eff_final.java
+ *
+ */
+
+class Neg04eff_final {
+    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 (Exception e) {
+            throw e;
+        }
+        catch (Throwable t) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg04eff_final.out	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg04eff_final.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg05.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,33 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author mcimadamore
+ * @compile/fail/ref=Neg05.out -XDrawDiagnostics Neg05.java
+ *
+ */
+
+class Neg02 {
+
+    static class Foo<X> {
+       Foo(X x) {}
+    }
+
+    static interface Base<X> {}
+    static class A extends Exception implements Base<String> {}
+    static class B extends Exception implements Base<Integer> {}
+
+    void m() {
+        try {
+            if (true) {
+                throw new A();
+            }
+            else {
+                throw new B();
+            }
+        } catch (A | B ex) {
+            Foo<?> f = new Foo<>(ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Neg05.out	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg05.java:30:31: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg02.Foo), (compiler.misc.diamond.invalid.arg: java.lang.Exception&Neg02.Base<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, (compiler.misc.diamond: Neg02.Foo))
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Pos06.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6993963
+ *
+ * @summary Project Coin: Use precise exception analysis for effectively final catch parameters
+ * @author mcimadamore
+ * @compile Pos06.java
+ *
+ */
+
+class Pos06 {
+    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) {
+            System.out.println(ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/Pos07.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6993963
+ * @summary Project Coin: Use precise exception analysis for effectively final catch parameters
+ * @compile Pos07.java
+ */
+
+class Pos07 {
+
+    static class A extends Exception { public void m() {}; public Object f;}
+    static class B1 extends A {}
+    static class B2 extends A {}
+
+    void m() throws B1, B2 {
+        try {
+            if (true) {
+                throw new B1();
+            }
+            else {
+                throw new B2();
+            }
+        } catch (Exception ex) { //effectively final analysis
+            throw ex;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/model/Check.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Annotation used by ModelChecker to mark the class whose model is to be checked
+ */
+@interface Check {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/model/Member.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.lang.model.element.ElementKind;
+
+/**
+ * Annotation used by ModelChecker to mark a member that is to be checked
+ */
+@interface Member {
+   ElementKind value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/model/Model01.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.lang.model.element.ElementKind;
+
+@Check
+class Test {
+
+    class A extends Exception {
+        @Member(ElementKind.METHOD)
+        public void m() {};
+        @Member(ElementKind.FIELD)
+        public Object f;
+    }
+
+    class B1 extends A {}
+    class B2 extends A {}
+
+    void test(){
+        try {
+            if (true)
+                throw new B1();
+            else
+                throw new B2();
+        }
+        catch(B1 | B2 ex) { }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/multicatch/model/ModelChecker.java	Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6993963
+ * @summary Project Coin: Use precise exception analysis for effectively final catch parameters
+ * @library ../../lib
+ * @build JavacTestingAbstractProcessor ModelChecker
+ * @compile -processor ModelChecker Model01.java
+ */
+
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import com.sun.source.util.TreePath;
+
+import java.util.Set;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+
+@SupportedAnnotationTypes("Check")
+public class ModelChecker extends JavacTestingAbstractProcessor {
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver())
+            return true;
+
+        Trees trees = Trees.instance(processingEnv);
+
+        TypeElement testAnno = elements.getTypeElement("Check");
+        for (Element elem: roundEnv.getElementsAnnotatedWith(testAnno)) {
+            TreePath p = trees.getPath(elem);
+            new MulticatchParamTester(trees).scan(p, null);
+        }
+        return true;
+    }
+
+    class MulticatchParamTester extends TreePathScanner<Void, Void> {
+        Trees trees;
+
+        public MulticatchParamTester(Trees trees) {
+            super();
+            this.trees = trees;
+        }
+
+        @Override
+        public Void visitVariable(VariableTree node, Void p) {
+            Element ex = trees.getElement(getCurrentPath());
+            if (ex.getSimpleName().contentEquals("ex")) {
+                assertTrue(ex.getKind() == ElementKind.EXCEPTION_PARAMETER, "Expected EXCEPTION_PARAMETER - found " + ex.getKind());
+                for (Element e : types.asElement(ex.asType()).getEnclosedElements()) {
+                    Member m = e.getAnnotation(Member.class);
+                    if (m != null) {
+                        assertTrue(e.getKind() == m.value(), "Expected " + m.value() + " - found " + e.getKind());
+                    }
+                }
+                assertTrue(assertionCount == 3, "Expected 3 assertions - found " + assertionCount);
+            }
+            return super.visitVariable(node, p);
+        }
+    }
+
+    private static void assertTrue(boolean cond, String msg) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError(msg);
+    }
+
+    static int assertionCount = 0;
+}