--- old/src/share/classes/com/sun/tools/javac/comp/Attr.java 2010-07-01 12:35:19.000000000 -0700 +++ new/src/share/classes/com/sun/tools/javac/comp/Attr.java 2010-07-01 12:35:19.000000000 -0700 @@ -197,7 +197,7 @@ Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) { if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) { if ((ownkind & ~pkind) == 0) { - owntype = chk.checkType(tree.pos(), owntype, pt); + owntype = chk.checkType(tree.pos(), owntype, pt, errKey); } else { log.error(tree.pos(), "unexpected.type", kindNames(pkind), @@ -244,7 +244,11 @@ !((base == null || (base.getTag() == JCTree.IDENT && TreeInfo.name(base) == names._this)) && isAssignableAsBlankFinal(v, env)))) { - log.error(pos, "cant.assign.val.to.final.var", v); + if (types.asSuper(v.type, syms.autoCloseableType.tsym) != null) { //ARM resource + log.error(pos, "arm.resource.may.not.be.assigned", v); + } else { + log.error(pos, "cant.assign.val.to.final.var", v); + } } } @@ -377,6 +381,10 @@ */ Type pt; + /** Visitor argument: the error key to be generated when a type error occurs + */ + String errKey; + /** Visitor result: the computed type. */ Type result; @@ -390,13 +398,19 @@ * @param pt The prototype visitor argument. */ Type attribTree(JCTree tree, Env env, int pkind, Type pt) { + return attribTree(tree, env, pkind, pt, "incompatible.types"); + } + + Type attribTree(JCTree tree, Env env, int pkind, Type pt, String errKey) { Env prevEnv = this.env; int prevPkind = this.pkind; Type prevPt = this.pt; + String prevErrKey = this.errKey; try { this.env = env; this.pkind = pkind; this.pt = pt; + this.errKey = errKey; tree.accept(this); if (tree == breakTree) throw new BreakAttr(env); @@ -408,6 +422,7 @@ this.env = prevEnv; this.pkind = prevPkind; this.pt = prevPt; + this.errKey = prevErrKey; } } @@ -417,6 +432,10 @@ return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType); } + public Type attribExpr(JCTree tree, Env env, Type pt, String key) { + return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType, key); + } + /** Derived visitor method: attribute an expression tree with * no constraints on the computed type. */ @@ -981,14 +1000,35 @@ } public void visitTry(JCTry tree) { + // Create a new local environment with a local scope. + Env localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); + // Attribute resource declarations + ListBuffer resourceVars = ListBuffer.lb(); + for (JCTree resource : tree.resources) { + if (resource.getTag() == JCTree.VARDEF) { + attribStat(resource, localEnv); + chk.checkType(resource, resource.type, syms.autoCloseableType, "arm.not.applicable.to.type"); + VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); + var.setData(ElementKind.RESOURCE_VARIABLE); + resourceVars.append(var); + } else { + attribExpr(resource, localEnv, syms.autoCloseableType, "arm.not.applicable.to.type"); + } + } // Attribute body - attribStat(tree.body, env.dup(tree, env.info.dup())); + attribStat(tree.body, localEnv.dup(tree, localEnv.info.dup())); + + //remove arm resource vars from local scope - such variables cannot be + //accessed from catch/finally clauses + for (VarSymbol resourceVar : resourceVars) { + localEnv.info.scope.remove(resourceVar); + } // Attribute catch clauses for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { JCCatch c = l.head; Env catchEnv = - env.dup(c, env.info.dup(env.info.scope.dup())); + 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 @@ -1008,7 +1048,9 @@ } // Attribute finalizer - if (tree.finalizer != null) attribStat(tree.finalizer, env); + if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); + + localEnv.info.scope.leave(); result = null; }