--- old/src/share/classes/com/sun/tools/javac/comp/Flow.java 2010-07-04 10:48:07.000000000 -0700 +++ new/src/share/classes/com/sun/tools/javac/comp/Flow.java 2010-07-04 10:48:06.000000000 -0700 @@ -37,6 +37,9 @@ import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; +import java.util.HashSet; +import java.util.Set; + import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTags.*; @@ -265,6 +268,10 @@ */ List caught; + /** The list of unreferenced automatic resources. + */ + Set unrefdResources; + /** Set when processing a loop body the second time for DU analysis. */ boolean loopPassTwo = false; @@ -963,6 +970,7 @@ public void visitTry(JCTry tree) { List caughtPrev = caught; List thrownPrev = thrown; + Set unrefdResourcesPrev = unrefdResources; thrown = List.nil(); for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { List subClauses = TreeInfo.isMultiCatch(l.head) ? @@ -977,6 +985,32 @@ pendingExits = new ListBuffer(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); + unrefdResources = new HashSet(); + for (JCTree resource : tree.resources) { + if (resource instanceof JCVariableDecl) { + JCVariableDecl vdecl = (JCVariableDecl) resource; + visitVarDef(vdecl); + unrefdResources.add(vdecl.sym); + } else if (resource instanceof JCExpression) { + scanExpr((JCExpression) resource); + } else { + throw new AssertionError(tree); // parser error + } + } + for (JCTree resource : tree.resources) { + MethodSymbol topCloseMethod = (MethodSymbol)syms.autoCloseableType.tsym.members().lookup(names.close).sym; + List closeableSupertypes = resource.type.isCompound() ? + types.interfaces(resource.type).prepend(types.supertype(resource.type)) : + List.of(resource.type); + for (Type sup : closeableSupertypes) { + if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) { + MethodSymbol closeMethod = types.implementation(topCloseMethod, sup.tsym, types, true); + for (Type t : closeMethod.getThrownTypes()) { + markThrown(tree.body, t); + } + } + } + } scanStat(tree.body); List thrownInTry = thrown; thrown = thrownPrev; @@ -987,6 +1021,14 @@ Bits uninitsEnd = uninits; int nextadrCatch = nextadr; + if (!unrefdResources.isEmpty() && + lint.isEnabled(Lint.LintCategory.ARM)) { + for (VarSymbol v : unrefdResources) { + log.warning(v.pos, + "automatic.resource.not.referenced", v); + } + } + List caughtInTry = List.nil(); for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { alive = true; @@ -1070,6 +1112,7 @@ while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); + unrefdResources = unrefdResourcesPrev; } public void visitConditional(JCConditional tree) { @@ -1293,8 +1336,16 @@ } public void visitIdent(JCIdent tree) { - if (tree.sym.kind == VAR) + if (tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); + referenced(tree.sym); + } + } + + void referenced(Symbol sym) { + if (unrefdResources != null && unrefdResources.contains(sym)) { + unrefdResources.remove(sym); + } } public void visitTypeCast(JCTypeCast tree) {