7196163: Project Coin: Allow effectively final variables to be used as resources in try-with-resources
authorjlahoda
Wed, 19 Nov 2014 13:46:04 +0100
changeset 27844 8b5d79870a2f
parent 27843 a032fe725c78
child 27845 afce9de2de10
7196163: Project Coin: Allow effectively final variables to be used as resources in try-with-resources Summary: Allowing final variables as operands to try-with-resources; also reviewed by Sergei Pikalev. Reviewed-by: darcy, mcimadamore, vromero
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out
langtools/test/tools/javac/TryWithResources/ResDeclOutsideTry.java
langtools/test/tools/javac/TryWithResources/ResDeclOutsideTry.out
langtools/test/tools/javac/TryWithResources/TwrForVariable1.java
langtools/test/tools/javac/TryWithResources/TwrForVariable1.out
langtools/test/tools/javac/TryWithResources/TwrForVariable2.java
langtools/test/tools/javac/TryWithResources/TwrForVariable2.out
langtools/test/tools/javac/TryWithResources/TwrForVariable3.java
langtools/test/tools/javac/TryWithResources/TwrForVariable3.out
langtools/test/tools/javac/TryWithResources/TwrForVariable4.java
langtools/test/tools/javac/TryWithResources/TwrForVariable4.out
langtools/test/tools/javac/diags/examples/TryWithResourcesExprEffectivelyFinalVar.java
langtools/test/tools/javac/diags/examples/TryWithResourcesExprNeedsVar.java
langtools/test/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java	Wed Nov 19 13:46:04 2014 +0100
@@ -168,6 +168,7 @@
         public static final KindSelector MTH = new KindSelector(0x10);
         public static final KindSelector ERR = new KindSelector(0x3f);
         public static final KindSelector POLY = new KindSelector(0x20);
+        public static final KindSelector ASG = new KindSelector(0x44);
 
         //common derived selectors
         public static final KindSelector TYP_PCK = of(TYP, PCK);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java	Wed Nov 19 13:46:04 2014 +0100
@@ -140,6 +140,9 @@
     public boolean allowTryWithResources() {
         return compareTo(JDK1_7) >= 0;
     }
+    public boolean allowEffectivelyFinalVariablesInTryWithResources() {
+        return compareTo(JDK1_9) >= 0;
+    }
     public boolean allowBinaryLiterals() {
         return compareTo(JDK1_7) >= 0;
     }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Nov 19 13:46:04 2014 +0100
@@ -148,7 +148,7 @@
         identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false);
 
         statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
-        varInfo = new ResultInfo(KindSelector.VAR, Type.noType);
+        varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
         unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
         unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly);
         unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
@@ -498,7 +498,7 @@
     }
 
     final ResultInfo statInfo;
-    final ResultInfo varInfo;
+    final ResultInfo varAssignmentInfo;
     final ResultInfo unknownAnyPolyInfo;
     final ResultInfo unknownExprInfo;
     final ResultInfo unknownTypeInfo;
@@ -1293,7 +1293,7 @@
                         }
                     };
                     ResultInfo twrResult =
-                        new ResultInfo(KindSelector.VAL,
+                        new ResultInfo(KindSelector.VAR,
                                        syms.autoCloseableType,
                                        twrContext);
                     if (resource.hasTag(VARDEF)) {
@@ -2942,7 +2942,7 @@
     }
 
     public void visitAssign(JCAssign tree) {
-        Type owntype = attribTree(tree.lhs, env.dup(tree), varInfo);
+        Type owntype = attribTree(tree.lhs, env.dup(tree), varAssignmentInfo);
         Type capturedType = capture(owntype);
         attribExpr(tree.rhs, env, owntype);
         result = check(tree, capturedType, KindSelector.VAL, resultInfo);
@@ -2950,7 +2950,7 @@
 
     public void visitAssignop(JCAssignOp tree) {
         // Attribute arguments.
-        Type owntype = attribTree(tree.lhs, env, varInfo);
+        Type owntype = attribTree(tree.lhs, env, varAssignmentInfo);
         Type operand = attribExpr(tree.rhs, env);
         // Find operator.
         Symbol operator = tree.operator = rs.resolveBinaryOperator(
@@ -2976,7 +2976,7 @@
     public void visitUnary(JCUnary tree) {
         // Attribute arguments.
         Type argtype = (tree.getTag().isIncOrDecUnaryOp())
-            ? attribTree(tree.arg, env, varInfo)
+            ? attribTree(tree.arg, env, varAssignmentInfo)
             : chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env));
 
         // Find operator.
@@ -3156,7 +3156,7 @@
 
             // If we are expecting a variable (as opposed to a value), check
             // that the variable is assignable in the current environment.
-            if (pkind() == KindSelector.VAR)
+            if (KindSelector.ASG.subset(pkind()))
                 checkAssignable(tree.pos(), v, null, env);
         }
 
@@ -3255,7 +3255,7 @@
 
             // If we are expecting a variable (as opposed to a value), check
             // that the variable is assignable in the current environment.
-            if (pkind() == KindSelector.VAR)
+            if (KindSelector.ASG.subset(pkind()))
                 checkAssignable(tree.pos(), v, tree.selected, env);
         }
 
@@ -3538,7 +3538,7 @@
                 // Test (4): if symbol is an instance field of a raw type,
                 // which is being assigned to, issue an unchecked warning if
                 // its type changes under erasure.
-                if (resultInfo.pkind == KindSelector.VAR &&
+                if (KindSelector.ASG.subset(pkind()) &&
                     v.owner.kind == TYP &&
                     (v.flags() & STATIC) == 0 &&
                     (site.hasTag(CLASS) || site.hasTag(TYPEVAR))) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Nov 19 13:46:04 2014 +0100
@@ -2562,6 +2562,8 @@
      * This pass implements the last step of the dataflow analysis, namely
      * the effectively-final analysis check. This checks that every local variable
      * reference from a lambda body/local inner class is either final or effectively final.
+     * Additional this also checks that every variable that is used as an operand to
+     * try-with-resources is final or effectively final.
      * As effectively final variables are marked as such during DA/DU, this pass must run after
      * AssignAnalyzer.
      */
@@ -2690,6 +2692,18 @@
             }
         }
 
+        public void visitTry(JCTry tree) {
+            for (JCTree resource : tree.resources) {
+                if (!resource.hasTag(VARDEF)) {
+                    Symbol var = TreeInfo.symbol(resource);
+                    if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
+                        log.error(resource.pos(), "try.with.resources.expr.effectively.final.var", var);
+                    }
+                }
+            }
+            super.visitTry(tree);
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Nov 19 13:46:04 2014 +0100
@@ -145,6 +145,8 @@
         this.names = fac.names;
         this.source = fac.source;
         this.allowTWR = source.allowTryWithResources();
+        this.allowEffectivelyFinalVariablesInTWR =
+                source.allowEffectivelyFinalVariablesInTryWithResources();
         this.allowDiamond = source.allowDiamond();
         this.allowMulticatch = source.allowMulticatch();
         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
@@ -184,6 +186,10 @@
      */
     boolean allowTWR;
 
+    /** Switch: should we allow (effectively) final variables as resources in try-with-resources?
+     */
+    boolean allowEffectivelyFinalVariablesInTWR;
+
     /** Switch: should we fold strings?
      */
     boolean allowStringFolding;
@@ -3003,14 +3009,28 @@
         return defs.toList();
     }
 
-    /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
+    /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
+     *           | Expression
      */
     protected JCTree resource() {
-        JCModifiers optFinal = optFinal(Flags.FINAL);
-        JCExpression type = parseType();
-        int pos = token.pos;
-        Name ident = ident();
-        return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
+        int startPos = token.pos;
+        if (token.kind == FINAL || token.kind == MONKEYS_AT) {
+            JCModifiers mods = optFinal(Flags.FINAL);
+            JCExpression t = parseType();
+            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
+        }
+        JCExpression t = term(EXPR | TYPE);
+        if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
+            JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL));
+            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
+        } else {
+            checkVariableInTryWithResources(startPos);
+            if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
+                log.error(t.pos(), "try.with.resources.expr.needs.var");
+            }
+
+            return t;
+        }
     }
 
     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
@@ -3933,6 +3953,12 @@
             allowTWR = true;
         }
     }
+    void checkVariableInTryWithResources(int startPos) {
+        if (!allowEffectivelyFinalVariablesInTWR) {
+            error(startPos, "var.in.try.with.resources.not.supported.in.source", source.name);
+            allowEffectivelyFinalVariablesInTWR = true;
+        }
+    }
     void checkLambda() {
         if (!allowLambda) {
             log.error(token.pos, "lambda.not.supported.in.source", source.name);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Nov 19 13:46:04 2014 +0100
@@ -252,6 +252,14 @@
 compiler.err.cant.ref.non.effectively.final.var=\
     local variables referenced from {1} must be final or effectively final
 
+compiler.err.try.with.resources.expr.needs.var=\
+    the try-with-resources resource must either be a variable declaration or an expression denoting \
+a reference to a final or effectively final variable
+
+# 0: symbol
+compiler.err.try.with.resources.expr.effectively.final.var=\
+    variable {0} used as a try-with-resources resource neither final nor effectively final
+
 
 compiler.misc.lambda=\
     a lambda expression
@@ -2262,6 +2270,11 @@
     try-with-resources is not supported in -source {0}\n\
     (use -source 7 or higher to enable try-with-resources)
 
+# 0: string
+compiler.err.var.in.try.with.resources.not.supported.in.source=\
+    variables in try-with-resources not supported in -source {0}\n\
+    (use -source 9 or higher to enable variables in try-with-resources)
+
 compiler.warn.underscore.as.identifier=\
     ''_'' used as an identifier\n\
     (use of ''_'' as an identifier might not be supported in releases after Java SE 8)
--- a/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out	Wed Nov 19 13:46:04 2014 +0100
@@ -1,2 +1,2 @@
-BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.type
+BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr
 1 error
--- a/langtools/test/tools/javac/TryWithResources/ResDeclOutsideTry.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/test/tools/javac/TryWithResources/ResDeclOutsideTry.java	Wed Nov 19 13:46:04 2014 +0100
@@ -13,6 +13,11 @@
     String test1() {
         try (tr1 = new ResDeclOutsideTry(); tr2;) {
         }
+        return null;
+    }
+
+    @Override
+    public void close() throws Exception {
     }
 }
 
--- a/langtools/test/tools/javac/TryWithResources/ResDeclOutsideTry.out	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/test/tools/javac/TryWithResources/ResDeclOutsideTry.out	Wed Nov 19 13:46:04 2014 +0100
@@ -1,3 +1,2 @@
-ResDeclOutsideTry.java:14:17: compiler.err.expected: token.identifier
-ResDeclOutsideTry.java:14:48: compiler.err.expected: token.identifier
-2 errors
+ResDeclOutsideTry.java:14:18: compiler.err.try.with.resources.expr.needs.var
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable1.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,69 @@
+/* @test /nodynamiccopyright/
+ * @bug 7196163
+ * @summary Verify that variables can be used as operands to try-with-resources
+ * @compile/fail/ref=TwrForVariable1.out -source 8 -XDrawDiagnostics -Xlint:-options TwrForVariable1.java
+ * @compile TwrForVariable1.java
+ * @run main TwrForVariable1
+ */
+public class TwrForVariable1 implements AutoCloseable {
+    private static int closeCount = 0;
+    public static void main(String... args) {
+        TwrForVariable1 v = new TwrForVariable1();
+
+        try (v) {
+            assertCloseCount(0);
+        }
+        try (/**@deprecated*/v) {
+            assertCloseCount(1);
+        }
+        try (v.finalWrapper.finalField) {
+            assertCloseCount(2);
+        } catch (Exception ex) {
+        }
+        try (new TwrForVariable1() { }.finalWrapper.finalField) {
+            assertCloseCount(3);
+        } catch (Exception ex) {
+        }
+        try ((args.length > 0 ? v : new TwrForVariable1()).finalWrapper.finalField) {
+            assertCloseCount(4);
+        } catch (Exception ex) {
+        }
+        try {
+            throw new CloseableException();
+        } catch (CloseableException ex) {
+            try (ex) {
+                assertCloseCount(5);
+            }
+        }
+
+        assertCloseCount(6);
+    }
+
+    static void assertCloseCount(int expectedCloseCount) {
+        if (closeCount != expectedCloseCount)
+            throw new RuntimeException("bad closeCount: " + closeCount +
+                                       "; expected: " + expectedCloseCount);
+    }
+
+    public void close() {
+        closeCount++;
+    }
+
+    final FinalWrapper finalWrapper = new FinalWrapper();
+
+    static class FinalWrapper {
+        public final AutoCloseable finalField = new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+                closeCount++;
+            }
+        };
+    }
+
+    static class CloseableException extends Exception implements AutoCloseable {
+        @Override
+        public void close() {
+            closeCount++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable1.out	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,2 @@
+TwrForVariable1.java:13:14: compiler.err.var.in.try.with.resources.not.supported.in.source: 1.8
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable2.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,39 @@
+/* @test /nodynamiccopyright/
+ * @bug 7196163
+ * @summary Verify that an improper combination of modifiers and variable is rejected
+ *          in an operand to try-with-resources
+ * @compile/fail/ref=TwrForVariable2.out -XDrawDiagnostics -Xlint:-options TwrForVariable2.java
+ */
+public class TwrForVariable2 implements AutoCloseable {
+    public static void main(String... args) {
+        TwrForVariable2 v = new TwrForVariable2();
+        TwrForVariable3[] v2 = new TwrForVariable3[1];
+
+        try (final v) {
+            fail("no modifiers before variables");
+        }
+        try (@Deprecated v) {
+            fail("no annotations before variables");
+        }
+        try (v;;) {
+            fail("illegal double semicolon");
+        }
+        try ((v)) {
+            fail("parentheses not allowed");
+        }
+        try (v2[0]) {
+            fail("array access not allowed");
+        }
+        try (args.length == 0 ? v : v) {
+            fail("general expressions not allowed");
+        }
+    }
+
+    static void fail(String reason) {
+        throw new RuntimeException(reason);
+    }
+
+    public void close() {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable2.out	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,7 @@
+TwrForVariable2.java:12:21: compiler.err.expected: token.identifier
+TwrForVariable2.java:15:27: compiler.err.expected: token.identifier
+TwrForVariable2.java:18:16: compiler.err.illegal.start.of.expr
+TwrForVariable2.java:21:14: compiler.err.try.with.resources.expr.needs.var
+TwrForVariable2.java:24:16: compiler.err.try.with.resources.expr.needs.var
+TwrForVariable2.java:27:31: compiler.err.try.with.resources.expr.needs.var
+6 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,29 @@
+/* @test /nodynamiccopyright/
+ * @bug 7196163
+ * @summary Verify that improper expressions used as an operand to try-with-resources are rejected.
+ * @compile/fail/ref=TwrForVariable3.out -XDrawDiagnostics -Xlint:-options TwrForVariable3.java
+ */
+public class TwrForVariable3 implements AutoCloseable {
+    public static void main(String... args) {
+        TwrForVariable3 v1 = new TwrForVariable3();
+        Object v2 = new Object();
+
+        try (v2) {
+            fail("no an AutoCloseable");
+        }
+        try (java.lang.Object) {
+            fail("not a variable access");
+        }
+        try (java.lang) {
+            fail("not a variable access");
+        }
+    }
+
+    static void fail(String reason) {
+        throw new RuntimeException(reason);
+    }
+
+    public void close() {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,4 @@
+TwrForVariable3.java:11:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable))
+TwrForVariable3.java:14:18: compiler.err.cant.resolve.location: kindname.class, lang, , , (compiler.misc.location: kindname.package, java, null)
+TwrForVariable3.java:17:14: compiler.err.cant.resolve.location: kindname.variable, java, , , (compiler.misc.location: kindname.class, TwrForVariable3, null)
+3 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable4.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,45 @@
+/* @test /nodynamiccopyright/
+ * @bug 7196163
+ * @summary Verify that variable used as an operand to try-with-resources is rejected if it is not
+ *          definitelly assigned before use and or not final or effectivelly final.
+ * @compile/fail/ref=TwrForVariable4.out -XDrawDiagnostics -Xlint:-options TwrForVariable4.java
+ */
+public class TwrForVariable4 implements AutoCloseable {
+    public static void main(String... args) {
+        TwrForVariable4 uninitialized;
+
+        try (uninitialized) {
+            fail("must be initialized before use");
+        }
+        uninitialized = new TwrForVariable4();
+
+        TwrForVariable4 notEffectivellyFinal1 = new TwrForVariable4();
+
+        notEffectivellyFinal1 = new TwrForVariable4();
+
+        try (notEffectivellyFinal1) {
+            fail("not effectivelly final");
+        }
+
+        TwrForVariable4 notEffectivellyFinal2 = new TwrForVariable4();
+
+        try (notEffectivellyFinal2) {
+            notEffectivellyFinal2 = new TwrForVariable4();
+            fail("not effectivelly final");
+        }
+
+        try (notFinal) {
+            fail("not final");
+        }
+    }
+
+    static TwrForVariable4 notFinal = new TwrForVariable4();
+
+    static void fail(String reason) {
+        throw new RuntimeException(reason);
+    }
+
+    public void close() {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable4.out	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,5 @@
+TwrForVariable4.java:11:14: compiler.err.var.might.not.have.been.initialized: uninitialized
+TwrForVariable4.java:20:14: compiler.err.try.with.resources.expr.effectively.final.var: notEffectivellyFinal1
+TwrForVariable4.java:26:14: compiler.err.try.with.resources.expr.effectively.final.var: notEffectivellyFinal2
+TwrForVariable4.java:31:14: compiler.err.try.with.resources.expr.effectively.final.var: notFinal
+4 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TryWithResourcesExprEffectivelyFinalVar.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 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.try.with.resources.expr.effectively.final.var
+
+class TryWithResourcesExprEffectivelyFinalVar {
+    void m() {
+        CloseableImpl ac = new CloseableImpl();
+
+        try (ac) {
+            ac = null;
+        }
+    }
+}
+
+class CloseableImpl implements AutoCloseable {
+    @Override
+    public void close() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TryWithResourcesExprNeedsVar.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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.try.with.resources.expr.needs.var
+
+class TryWithResourcesExprNeedsVar {
+    void m() {
+        try (new CloseableImpl()) {
+        }
+    }
+}
+
+class CloseableImpl implements AutoCloseable {
+    @Override
+    public void close() throws Exception {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java	Wed Nov 19 13:46:04 2014 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 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.var.in.try.with.resources.not.supported.in.source
+// key: compiler.warn.source.no.bootclasspath
+// options: -source 8
+
+class VarInTryWithResourcesNotSupportedInSource {
+    void m() {
+        AutoCloseable ac = new CloseableImpl();
+
+        try (ac) {
+        }
+    }
+}
+
+class CloseableImpl implements AutoCloseable {
+    @Override
+    public void close() throws Exception {
+    }
+}