langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 45504 ea7475564d07
parent 42828 cce89649f958
equal deleted inserted replaced
45503:d23ae2d67a5d 45504:ea7475564d07
    30 import java.util.HashMap;
    30 import java.util.HashMap;
    31 
    31 
    32 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
    32 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
    33 import com.sun.tools.javac.code.*;
    33 import com.sun.tools.javac.code.*;
    34 import com.sun.tools.javac.code.Scope.WriteableScope;
    34 import com.sun.tools.javac.code.Scope.WriteableScope;
       
    35 import com.sun.tools.javac.resources.CompilerProperties.Errors;
       
    36 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
    35 import com.sun.tools.javac.tree.*;
    37 import com.sun.tools.javac.tree.*;
    36 import com.sun.tools.javac.util.*;
    38 import com.sun.tools.javac.util.*;
    37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    38 
    40 
    39 import com.sun.tools.javac.code.Symbol.*;
    41 import com.sun.tools.javac.code.Symbol.*;
   425          */
   427          */
   426         void scanDef(JCTree tree) {
   428         void scanDef(JCTree tree) {
   427             scanStat(tree);
   429             scanStat(tree);
   428             if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
   430             if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
   429                 log.error(tree.pos(),
   431                 log.error(tree.pos(),
   430                           "initializer.must.be.able.to.complete.normally");
   432                           Errors.InitializerMustBeAbleToCompleteNormally);
   431             }
   433             }
   432         }
   434         }
   433 
   435 
   434         /** Analyze a statement. Check that statement is reachable.
   436         /** Analyze a statement. Check that statement is reachable.
   435          */
   437          */
   436         void scanStat(JCTree tree) {
   438         void scanStat(JCTree tree) {
   437             if (!alive && tree != null) {
   439             if (!alive && tree != null) {
   438                 log.error(tree.pos(), "unreachable.stmt");
   440                 log.error(tree.pos(), Errors.UnreachableStmt);
   439                 if (!tree.hasTag(SKIP)) alive = true;
   441                 if (!tree.hasTag(SKIP)) alive = true;
   440             }
   442             }
   441             scan(tree);
   443             scan(tree);
   442         }
   444         }
   443 
   445 
   501             try {
   503             try {
   502                 alive = true;
   504                 alive = true;
   503                 scanStat(tree.body);
   505                 scanStat(tree.body);
   504 
   506 
   505                 if (alive && !tree.sym.type.getReturnType().hasTag(VOID))
   507                 if (alive && !tree.sym.type.getReturnType().hasTag(VOID))
   506                     log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
   508                     log.error(TreeInfo.diagEndPos(tree.body), Errors.MissingRetStmt);
   507 
   509 
   508                 List<PendingExit> exits = pendingExits.toList();
   510                 List<PendingExit> exits = pendingExits.toList();
   509                 pendingExits = new ListBuffer<>();
   511                 pendingExits = new ListBuffer<>();
   510                 while (exits.nonEmpty()) {
   512                 while (exits.nonEmpty()) {
   511                     PendingExit exit = exits.head;
   513                     PendingExit exit = exits.head;
   606                 if (alive &&
   608                 if (alive &&
   607                     lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
   609                     lint.isEnabled(Lint.LintCategory.FALLTHROUGH) &&
   608                     c.stats.nonEmpty() && l.tail.nonEmpty())
   610                     c.stats.nonEmpty() && l.tail.nonEmpty())
   609                     log.warning(Lint.LintCategory.FALLTHROUGH,
   611                     log.warning(Lint.LintCategory.FALLTHROUGH,
   610                                 l.tail.head.pos(),
   612                                 l.tail.head.pos(),
   611                                 "possible.fall-through.into.case");
   613                                 Warnings.PossibleFallThroughIntoCase);
   612             }
   614             }
   613             if (!hasDefault) {
   615             if (!hasDefault) {
   614                 alive = true;
   616                 alive = true;
   615             }
   617             }
   616             alive |= resolveBreaks(tree, prevPendingExits);
   618             alive |= resolveBreaks(tree, prevPendingExits);
   648                 tree.finallyCanCompleteNormally = alive;
   650                 tree.finallyCanCompleteNormally = alive;
   649                 if (!alive) {
   651                 if (!alive) {
   650                     if (lint.isEnabled(Lint.LintCategory.FINALLY)) {
   652                     if (lint.isEnabled(Lint.LintCategory.FINALLY)) {
   651                         log.warning(Lint.LintCategory.FINALLY,
   653                         log.warning(Lint.LintCategory.FINALLY,
   652                                 TreeInfo.diagEndPos(tree.finalizer),
   654                                 TreeInfo.diagEndPos(tree.finalizer),
   653                                 "finally.cannot.complete");
   655                                 Warnings.FinallyCannotComplete);
   654                     }
   656                     }
   655                 } else {
   657                 } else {
   656                     while (exits.nonEmpty()) {
   658                     while (exits.nonEmpty()) {
   657                         pendingExits.append(exits.next());
   659                         pendingExits.append(exits.next());
   658                     }
   660                     }
   809                  exit != null;
   811                  exit != null;
   810                  exit = pendingExits.next()) {
   812                  exit = pendingExits.next()) {
   811                 if (classDef != null &&
   813                 if (classDef != null &&
   812                     classDef.pos == exit.tree.pos) {
   814                     classDef.pos == exit.tree.pos) {
   813                     log.error(exit.tree.pos(),
   815                     log.error(exit.tree.pos(),
   814                             "unreported.exception.default.constructor",
   816                               Errors.UnreportedExceptionDefaultConstructor(exit.thrown));
   815                             exit.thrown);
       
   816                 } else if (exit.tree.hasTag(VARDEF) &&
   817                 } else if (exit.tree.hasTag(VARDEF) &&
   817                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
   818                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
   818                     log.error(exit.tree.pos(),
   819                     log.error(exit.tree.pos(),
   819                             "unreported.exception.implicit.close",
   820                               Errors.UnreportedExceptionImplicitClose(exit.thrown,
   820                             exit.thrown,
   821                                                                       ((JCVariableDecl)exit.tree).sym.name));
   821                             ((JCVariableDecl)exit.tree).sym.name);
       
   822                 } else {
   822                 } else {
   823                     log.error(exit.tree.pos(),
   823                     log.error(exit.tree.pos(),
   824                             "unreported.exception.need.to.catch.or.throw",
   824                               Errors.UnreportedExceptionNeedToCatchOrThrow(exit.thrown));
   825                             exit.thrown);
       
   826                 }
   825                 }
   827             }
   826             }
   828         }
   827         }
   829 
   828 
   830         /** Record that exception is potentially thrown and check that it
   829         /** Record that exception is potentially thrown and check that it
  1168             }
  1167             }
  1169         }
  1168         }
  1170 
  1169 
  1171         void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
  1170         void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
  1172             if (chk.subset(exc, caughtInTry)) {
  1171             if (chk.subset(exc, caughtInTry)) {
  1173                 log.error(pos, "except.already.caught", exc);
  1172                 log.error(pos, Errors.ExceptAlreadyCaught(exc));
  1174             } else if (!chk.isUnchecked(pos, exc) &&
  1173             } else if (!chk.isUnchecked(pos, exc) &&
  1175                     !isExceptionOrThrowable(exc) &&
  1174                     !isExceptionOrThrowable(exc) &&
  1176                     !chk.intersects(exc, thrownInTry)) {
  1175                     !chk.intersects(exc, thrownInTry)) {
  1177                 log.error(pos, "except.never.thrown.in.try", exc);
  1176                 log.error(pos, Errors.ExceptNeverThrownInTry(exc));
  1178             } else if (allowImprovedCatchAnalysis) {
  1177             } else if (allowImprovedCatchAnalysis) {
  1179                 List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
  1178                 List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
  1180                 // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
  1179                 // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
  1181                 // unchecked exception, the result list would not be empty, as the augmented
  1180                 // unchecked exception, the result list would not be empty, as the augmented
  1182                 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
  1181                 // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
  1608                     }
  1607                     }
  1609                 }
  1608                 }
  1610                 else if ((sym.flags() & FINAL) != 0) {
  1609                 else if ((sym.flags() & FINAL) != 0) {
  1611                     if ((sym.flags() & PARAMETER) != 0) {
  1610                     if ((sym.flags() & PARAMETER) != 0) {
  1612                         if ((sym.flags() & UNION) != 0) { //multi-catch parameter
  1611                         if ((sym.flags() & UNION) != 0) { //multi-catch parameter
  1613                             log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
  1612                             log.error(pos, Errors.MulticatchParameterMayNotBeAssigned(sym));
  1614                         }
  1613                         }
  1615                         else {
  1614                         else {
  1616                             log.error(pos, "final.parameter.may.not.be.assigned",
  1615                             log.error(pos,
  1617                                   sym);
  1616                                       Errors.FinalParameterMayNotBeAssigned(sym));
  1618                         }
  1617                         }
  1619                     } else if (!uninits.isMember(sym.adr)) {
  1618                     } else if (!uninits.isMember(sym.adr)) {
  1620                         log.error(pos, flowKind.errKey, sym);
  1619                         log.error(pos, flowKind.errKey, sym);
  1621                     } else {
  1620                     } else {
  1622                         uninit(sym);
  1621                         uninit(sym);
  1623                     }
  1622                     }
  1624                 }
  1623                 }
  1625                 inits.incl(sym.adr);
  1624                 inits.incl(sym.adr);
  1626             } else if ((sym.flags() & FINAL) != 0) {
  1625             } else if ((sym.flags() & FINAL) != 0) {
  1627                 log.error(pos, "var.might.already.be.assigned", sym);
  1626                 log.error(pos, Errors.VarMightAlreadyBeAssigned(sym));
  1628             }
  1627             }
  1629         }
  1628         }
  1630         //where
  1629         //where
  1631             void uninit(VarSymbol sym) {
  1630             void uninit(VarSymbol sym) {
  1632                 if (!inits.isMember(sym.adr)) {
  1631                 if (!inits.isMember(sym.adr)) {
  2188             if (!resourceVarDecls.isEmpty() &&
  2187             if (!resourceVarDecls.isEmpty() &&
  2189                     lint.isEnabled(Lint.LintCategory.TRY)) {
  2188                     lint.isEnabled(Lint.LintCategory.TRY)) {
  2190                 for (JCVariableDecl resVar : resourceVarDecls) {
  2189                 for (JCVariableDecl resVar : resourceVarDecls) {
  2191                     if (unrefdResources.includes(resVar.sym)) {
  2190                     if (unrefdResources.includes(resVar.sym)) {
  2192                         log.warning(Lint.LintCategory.TRY, resVar.pos(),
  2191                         log.warning(Lint.LintCategory.TRY, resVar.pos(),
  2193                                     "try.resource.not.referenced", resVar.sym);
  2192                                     Warnings.TryResourceNotReferenced(resVar.sym));
  2194                         unrefdResources.remove(resVar.sym);
  2193                         unrefdResources.remove(resVar.sym);
  2195                     }
  2194                     }
  2196                 }
  2195                 }
  2197             }
  2196             }
  2198 
  2197 
  2599         }
  2598         }
  2600 
  2599 
  2601         void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
  2600         void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
  2602             String subKey = currentTree.hasTag(LAMBDA) ?
  2601             String subKey = currentTree.hasTag(LAMBDA) ?
  2603                   "lambda"  : "inner.cls";
  2602                   "lambda"  : "inner.cls";
  2604             log.error(pos, "cant.ref.non.effectively.final.var", sym, diags.fragment(subKey));
  2603             log.error(pos, Errors.CantRefNonEffectivelyFinalVar(sym, diags.fragment(subKey)));
  2605         }
  2604         }
  2606 
  2605 
  2607         void reportInnerClsNeedsFinalError(DiagnosticPosition pos, Symbol sym) {
  2606         void reportInnerClsNeedsFinalError(DiagnosticPosition pos, Symbol sym) {
  2608             log.error(pos,
  2607             log.error(pos,
  2609                     "local.var.accessed.from.icls.needs.final",
  2608                       Errors.LocalVarAccessedFromIclsNeedsFinal(sym));
  2610                     sym);
       
  2611         }
  2609         }
  2612 
  2610 
  2613     /*************************************************************************
  2611     /*************************************************************************
  2614      * Visitor methods for statements and definitions
  2612      * Visitor methods for statements and definitions
  2615      *************************************************************************/
  2613      *************************************************************************/
  2674         public void visitTry(JCTry tree) {
  2672         public void visitTry(JCTry tree) {
  2675             for (JCTree resource : tree.resources) {
  2673             for (JCTree resource : tree.resources) {
  2676                 if (!resource.hasTag(VARDEF)) {
  2674                 if (!resource.hasTag(VARDEF)) {
  2677                     Symbol var = TreeInfo.symbol(resource);
  2675                     Symbol var = TreeInfo.symbol(resource);
  2678                     if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
  2676                     if (var != null && (var.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
  2679                         log.error(resource.pos(), "try.with.resources.expr.effectively.final.var", var);
  2677                         log.error(resource.pos(), Errors.TryWithResourcesExprEffectivelyFinalVar(var));
  2680                     }
  2678                     }
  2681                 }
  2679                 }
  2682             }
  2680             }
  2683             super.visitTry(tree);
  2681             super.visitTry(tree);
  2684         }
  2682         }