src/share/classes/com/sun/tools/javac/comp/Flow.java

Print this page

        

*** 35,44 **** --- 35,47 ---- import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 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.*; /** This pass implements dataflow analysis for Java programs.
*** 263,272 **** --- 266,279 ---- /** The list of exceptions that are either caught or declared to be * thrown. */ List<Type> caught; + /** The list of unreferenced automatic resources. + */ + Set<VarSymbol> unrefdResources; + /** Set when processing a loop body the second time for DU analysis. */ boolean loopPassTwo = false; /*-------------------- Environments ----------------------*/
*** 961,970 **** --- 968,978 ---- } public void visitTry(JCTry tree) { List<Type> caughtPrev = caught; List<Type> thrownPrev = thrown; + Set<VarSymbol> unrefdResourcesPrev = unrefdResources; thrown = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ? ((JCTypeDisjoint)l.head.param.vartype).components : List.of(l.head.param.vartype);
*** 975,994 **** --- 983,1036 ---- Bits uninitsTryPrev = uninitsTry; ListBuffer<PendingExit> prevPendingExits = pendingExits; pendingExits = new ListBuffer<PendingExit>(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); + unrefdResources = new HashSet<VarSymbol>(); + 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<Type> 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<Type> thrownInTry = thrown; thrown = thrownPrev; caught = caughtPrev; boolean aliveEnd = alive; uninitsTry.andSet(uninits); Bits initsEnd = inits; 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<Type> caughtInTry = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { alive = true; JCVariableDecl param = l.head.param; List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
*** 1068,1077 **** --- 1110,1120 ---- ListBuffer<PendingExit> exits = pendingExits; pendingExits = prevPendingExits; while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); + unrefdResources = unrefdResourcesPrev; } public void visitConditional(JCConditional tree) { scanCond(tree.cond); Bits initsBeforeElse = initsWhenFalse;
*** 1291,1302 **** // annotations don't get scanned tree.underlyingType.accept(this); } public void visitIdent(JCIdent tree) { ! if (tree.sym.kind == VAR) checkInit(tree.pos(), (VarSymbol)tree.sym); } public void visitTypeCast(JCTypeCast tree) { super.visitTypeCast(tree); if (!tree.type.isErroneous() --- 1334,1353 ---- // annotations don't get scanned tree.underlyingType.accept(this); } public void visitIdent(JCIdent tree) { ! 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) { super.visitTypeCast(tree); if (!tree.type.isErroneous()