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

Print this page




  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 //todo: one might eliminate uninits.andSets when monotonic
  27 
  28 package com.sun.tools.javac.comp;
  29 
  30 import java.util.HashMap;


  31 
  32 import com.sun.tools.javac.code.*;
  33 import com.sun.tools.javac.tree.*;
  34 import com.sun.tools.javac.util.*;
  35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  36 
  37 import com.sun.tools.javac.code.Symbol.*;
  38 import com.sun.tools.javac.tree.JCTree.*;
  39 
  40 import static com.sun.tools.javac.code.Flags.*;
  41 import static com.sun.tools.javac.code.Kinds.*;
  42 import static com.sun.tools.javac.code.TypeTags.*;
  43 
  44 /** This pass implements dataflow analysis for Java programs.
  45  *  Liveness analysis checks that every statement is reachable.
  46  *  Exception analysis ensures that every checked exception that is
  47  *  thrown is declared or caught.  Definite assignment analysis
  48  *  ensures that each variable is assigned when used.  Definite
  49  *  unassignment analysis ensures that no final variable is assigned
  50  *  more than once.


 248      */
 249     JCClassDecl classDef;
 250 
 251     /** The first variable sequence number in this class definition.
 252      */
 253     int firstadr;
 254 
 255     /** The next available variable sequence number.
 256      */
 257     int nextadr;
 258 
 259     /** The list of possibly thrown declarable exceptions.
 260      */
 261     List<Type> thrown;
 262 
 263     /** The list of exceptions that are either caught or declared to be
 264      *  thrown.
 265      */
 266     List<Type> caught;
 267 




 268     /** Set when processing a loop body the second time for DU analysis. */
 269     boolean loopPassTwo = false;
 270 
 271     /*-------------------- Environments ----------------------*/
 272 
 273     /** A pending exit.  These are the statements return, break, and
 274      *  continue.  In addition, exception-throwing expressions or
 275      *  statements are put here when not known to be caught.  This
 276      *  will typically result in an error unless it is within a
 277      *  try-finally whose finally block cannot complete normally.
 278      */
 279     static class PendingExit {
 280         JCTree tree;
 281         Bits inits;
 282         Bits uninits;
 283         Type thrown;
 284         PendingExit(JCTree tree, Bits inits, Bits uninits) {
 285             this.tree = tree;
 286             this.inits = inits.dup();
 287             this.uninits = uninits.dup();


 946         alive |= resolveBreaks(tree, prevPendingExits);
 947         nextadr = nextadrPrev;
 948     }
 949     // where
 950         /** Add any variables defined in stats to inits and uninits. */
 951         private static void addVars(List<JCStatement> stats, Bits inits,
 952                                     Bits uninits) {
 953             for (;stats.nonEmpty(); stats = stats.tail) {
 954                 JCTree stat = stats.head;
 955                 if (stat.getTag() == JCTree.VARDEF) {
 956                     int adr = ((JCVariableDecl) stat).sym.adr;
 957                     inits.excl(adr);
 958                     uninits.incl(adr);
 959                 }
 960             }
 961         }
 962 
 963     public void visitTry(JCTry tree) {
 964         List<Type> caughtPrev = caught;
 965         List<Type> thrownPrev = thrown;

 966         thrown = List.nil();
 967         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
 968             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
 969                     ((JCTypeDisjoint)l.head.param.vartype).components :
 970                     List.of(l.head.param.vartype);
 971             for (JCExpression ct : subClauses) {
 972                 caught = chk.incl(ct.type, caught);
 973             }
 974         }
 975         Bits uninitsTryPrev = uninitsTry;
 976         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 977         pendingExits = new ListBuffer<PendingExit>();
 978         Bits initsTry = inits.dup();
 979         uninitsTry = uninits.dup();


























 980         scanStat(tree.body);
 981         List<Type> thrownInTry = thrown;
 982         thrown = thrownPrev;
 983         caught = caughtPrev;
 984         boolean aliveEnd = alive;
 985         uninitsTry.andSet(uninits);
 986         Bits initsEnd = inits;
 987         Bits uninitsEnd = uninits;
 988         int nextadrCatch = nextadr;
 989 








 990         List<Type> caughtInTry = List.nil();
 991         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
 992             alive = true;
 993             JCVariableDecl param = l.head.param;
 994             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
 995                     ((JCTypeDisjoint)l.head.param.vartype).components :
 996                     List.of(l.head.param.vartype);
 997             List<Type> ctypes = List.nil();
 998             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
 999             for (JCExpression ct : subClauses) {
1000                 Type exc = ct.type;
1001                 ctypes = ctypes.append(exc);
1002                 if (types.isSameType(exc, syms.objectType))
1003                     continue;
1004                 if (chk.subset(exc, caughtInTry)) {
1005                     log.error(l.head.pos(),
1006                               "except.already.caught", exc);
1007                 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1008                            exc.tsym != syms.throwableType.tsym &&
1009                            exc.tsym != syms.exceptionType.tsym &&


1053                     PendingExit exit = exits.next();
1054                     if (exit.inits != null) {
1055                         exit.inits.orSet(inits);
1056                         exit.uninits.andSet(uninits);
1057                     }
1058                     pendingExits.append(exit);
1059                 }
1060                 inits.orSet(initsEnd);
1061                 alive = aliveEnd;
1062             }
1063         } else {
1064             thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1065             inits = initsEnd;
1066             uninits = uninitsEnd;
1067             alive = aliveEnd;
1068             ListBuffer<PendingExit> exits = pendingExits;
1069             pendingExits = prevPendingExits;
1070             while (exits.nonEmpty()) pendingExits.append(exits.next());
1071         }
1072         uninitsTry.andSet(uninitsTryPrev).andSet(uninits);

1073     }
1074 
1075     public void visitConditional(JCConditional tree) {
1076         scanCond(tree.cond);
1077         Bits initsBeforeElse = initsWhenFalse;
1078         Bits uninitsBeforeElse = uninitsWhenFalse;
1079         inits = initsWhenTrue;
1080         uninits = uninitsWhenTrue;
1081         if (tree.truepart.type.tag == BOOLEAN &&
1082             tree.falsepart.type.tag == BOOLEAN) {
1083             // if b and c are boolean valued, then
1084             // v is (un)assigned after a?b:c when true iff
1085             //    v is (un)assigned after b when true and
1086             //    v is (un)assigned after c when true
1087             scanCond(tree.truepart);
1088             Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
1089             Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
1090             Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
1091             Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
1092             inits = initsBeforeElse;


1276             Bits initsWhenTrueLeft = initsWhenTrue;
1277             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1278             inits = initsWhenFalse;
1279             uninits = uninitsWhenFalse;
1280             scanCond(tree.rhs);
1281             initsWhenTrue.andSet(initsWhenTrueLeft);
1282             uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1283             break;
1284         default:
1285             scanExpr(tree.lhs);
1286             scanExpr(tree.rhs);
1287         }
1288     }
1289 
1290     public void visitAnnotatedType(JCAnnotatedType tree) {
1291         // annotations don't get scanned
1292         tree.underlyingType.accept(this);
1293     }
1294 
1295     public void visitIdent(JCIdent tree) {
1296         if (tree.sym.kind == VAR)
1297             checkInit(tree.pos(), (VarSymbol)tree.sym);








1298     }
1299 
1300     public void visitTypeCast(JCTypeCast tree) {
1301         super.visitTypeCast(tree);
1302         if (!tree.type.isErroneous()
1303             && lint.isEnabled(Lint.LintCategory.CAST)
1304             && types.isSameType(tree.expr.type, tree.clazz.type)
1305             && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) {
1306             log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1307         }
1308     }
1309 
1310     public void visitTopLevel(JCCompilationUnit tree) {
1311         // Do nothing for TopLevel since each class is visited individually
1312     }
1313 
1314 /**************************************************************************
1315  * utility methods for ignoring type-annotated casts lint checking
1316  *************************************************************************/
1317     private static final boolean ignoreAnnotatedCasts = true;




  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 //todo: one might eliminate uninits.andSets when monotonic
  27 
  28 package com.sun.tools.javac.comp;
  29 
  30 import java.util.HashMap;
  31 import java.util.Map;
  32 import java.util.LinkedHashMap;
  33 
  34 import com.sun.tools.javac.code.*;
  35 import com.sun.tools.javac.tree.*;
  36 import com.sun.tools.javac.util.*;
  37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  38 
  39 import com.sun.tools.javac.code.Symbol.*;
  40 import com.sun.tools.javac.tree.JCTree.*;
  41 
  42 import static com.sun.tools.javac.code.Flags.*;
  43 import static com.sun.tools.javac.code.Kinds.*;
  44 import static com.sun.tools.javac.code.TypeTags.*;
  45 
  46 /** This pass implements dataflow analysis for Java programs.
  47  *  Liveness analysis checks that every statement is reachable.
  48  *  Exception analysis ensures that every checked exception that is
  49  *  thrown is declared or caught.  Definite assignment analysis
  50  *  ensures that each variable is assigned when used.  Definite
  51  *  unassignment analysis ensures that no final variable is assigned
  52  *  more than once.


 250      */
 251     JCClassDecl classDef;
 252 
 253     /** The first variable sequence number in this class definition.
 254      */
 255     int firstadr;
 256 
 257     /** The next available variable sequence number.
 258      */
 259     int nextadr;
 260 
 261     /** The list of possibly thrown declarable exceptions.
 262      */
 263     List<Type> thrown;
 264 
 265     /** The list of exceptions that are either caught or declared to be
 266      *  thrown.
 267      */
 268     List<Type> caught;
 269 
 270     /** The list of unreferenced automatic resources.
 271      */
 272     Map<VarSymbol, JCVariableDecl> unrefdResources;
 273 
 274     /** Set when processing a loop body the second time for DU analysis. */
 275     boolean loopPassTwo = false;
 276 
 277     /*-------------------- Environments ----------------------*/
 278 
 279     /** A pending exit.  These are the statements return, break, and
 280      *  continue.  In addition, exception-throwing expressions or
 281      *  statements are put here when not known to be caught.  This
 282      *  will typically result in an error unless it is within a
 283      *  try-finally whose finally block cannot complete normally.
 284      */
 285     static class PendingExit {
 286         JCTree tree;
 287         Bits inits;
 288         Bits uninits;
 289         Type thrown;
 290         PendingExit(JCTree tree, Bits inits, Bits uninits) {
 291             this.tree = tree;
 292             this.inits = inits.dup();
 293             this.uninits = uninits.dup();


 952         alive |= resolveBreaks(tree, prevPendingExits);
 953         nextadr = nextadrPrev;
 954     }
 955     // where
 956         /** Add any variables defined in stats to inits and uninits. */
 957         private static void addVars(List<JCStatement> stats, Bits inits,
 958                                     Bits uninits) {
 959             for (;stats.nonEmpty(); stats = stats.tail) {
 960                 JCTree stat = stats.head;
 961                 if (stat.getTag() == JCTree.VARDEF) {
 962                     int adr = ((JCVariableDecl) stat).sym.adr;
 963                     inits.excl(adr);
 964                     uninits.incl(adr);
 965                 }
 966             }
 967         }
 968 
 969     public void visitTry(JCTry tree) {
 970         List<Type> caughtPrev = caught;
 971         List<Type> thrownPrev = thrown;
 972         Map<VarSymbol, JCVariableDecl> unrefdResourcesPrev = unrefdResources;
 973         thrown = List.nil();
 974         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
 975             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
 976                     ((JCTypeDisjoint)l.head.param.vartype).components :
 977                     List.of(l.head.param.vartype);
 978             for (JCExpression ct : subClauses) {
 979                 caught = chk.incl(ct.type, caught);
 980             }
 981         }
 982         Bits uninitsTryPrev = uninitsTry;
 983         ListBuffer<PendingExit> prevPendingExits = pendingExits;
 984         pendingExits = new ListBuffer<PendingExit>();
 985         Bits initsTry = inits.dup();
 986         uninitsTry = uninits.dup();
 987         unrefdResources = new LinkedHashMap<VarSymbol, JCVariableDecl>();
 988         for (JCTree resource : tree.resources) {
 989             if (resource instanceof JCVariableDecl) {
 990                 JCVariableDecl vdecl = (JCVariableDecl) resource;
 991                 visitVarDef(vdecl);
 992                 unrefdResources.put(vdecl.sym, vdecl);
 993             } else if (resource instanceof JCExpression) {
 994                 scanExpr((JCExpression) resource);
 995             } else {
 996                 throw new AssertionError(tree);  // parser error
 997             }
 998         }
 999         for (JCTree resource : tree.resources) {
1000             MethodSymbol topCloseMethod = (MethodSymbol)syms.autoCloseableType.tsym.members().lookup(names.close).sym;
1001             List<Type> closeableSupertypes = resource.type.isCompound() ?
1002                 types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
1003                 List.of(resource.type);
1004             for (Type sup : closeableSupertypes) {
1005                 if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
1006                     MethodSymbol closeMethod = types.implementation(topCloseMethod, sup.tsym, types, true);
1007                     for (Type t : closeMethod.getThrownTypes()) {
1008                         markThrown(tree.body, t);
1009                     }
1010                 }
1011             }
1012         }
1013         scanStat(tree.body);
1014         List<Type> thrownInTry = thrown;
1015         thrown = thrownPrev;
1016         caught = caughtPrev;
1017         boolean aliveEnd = alive;
1018         uninitsTry.andSet(uninits);
1019         Bits initsEnd = inits;
1020         Bits uninitsEnd = uninits;
1021         int nextadrCatch = nextadr;
1022 
1023         if (!unrefdResources.isEmpty() &&
1024                 lint.isEnabled(Lint.LintCategory.ARM)) {
1025             for (Map.Entry<VarSymbol, JCVariableDecl> e : unrefdResources.entrySet()) {
1026                 log.warning(e.getValue().pos(),
1027                             "automatic.resource.not.referenced", e.getKey());
1028             }
1029         }
1030 
1031         List<Type> caughtInTry = List.nil();
1032         for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1033             alive = true;
1034             JCVariableDecl param = l.head.param;
1035             List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1036                     ((JCTypeDisjoint)l.head.param.vartype).components :
1037                     List.of(l.head.param.vartype);
1038             List<Type> ctypes = List.nil();
1039             List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1040             for (JCExpression ct : subClauses) {
1041                 Type exc = ct.type;
1042                 ctypes = ctypes.append(exc);
1043                 if (types.isSameType(exc, syms.objectType))
1044                     continue;
1045                 if (chk.subset(exc, caughtInTry)) {
1046                     log.error(l.head.pos(),
1047                               "except.already.caught", exc);
1048                 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1049                            exc.tsym != syms.throwableType.tsym &&
1050                            exc.tsym != syms.exceptionType.tsym &&


1094                     PendingExit exit = exits.next();
1095                     if (exit.inits != null) {
1096                         exit.inits.orSet(inits);
1097                         exit.uninits.andSet(uninits);
1098                     }
1099                     pendingExits.append(exit);
1100                 }
1101                 inits.orSet(initsEnd);
1102                 alive = aliveEnd;
1103             }
1104         } else {
1105             thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
1106             inits = initsEnd;
1107             uninits = uninitsEnd;
1108             alive = aliveEnd;
1109             ListBuffer<PendingExit> exits = pendingExits;
1110             pendingExits = prevPendingExits;
1111             while (exits.nonEmpty()) pendingExits.append(exits.next());
1112         }
1113         uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1114         unrefdResources = unrefdResourcesPrev;
1115     }
1116 
1117     public void visitConditional(JCConditional tree) {
1118         scanCond(tree.cond);
1119         Bits initsBeforeElse = initsWhenFalse;
1120         Bits uninitsBeforeElse = uninitsWhenFalse;
1121         inits = initsWhenTrue;
1122         uninits = uninitsWhenTrue;
1123         if (tree.truepart.type.tag == BOOLEAN &&
1124             tree.falsepart.type.tag == BOOLEAN) {
1125             // if b and c are boolean valued, then
1126             // v is (un)assigned after a?b:c when true iff
1127             //    v is (un)assigned after b when true and
1128             //    v is (un)assigned after c when true
1129             scanCond(tree.truepart);
1130             Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
1131             Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
1132             Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
1133             Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
1134             inits = initsBeforeElse;


1318             Bits initsWhenTrueLeft = initsWhenTrue;
1319             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1320             inits = initsWhenFalse;
1321             uninits = uninitsWhenFalse;
1322             scanCond(tree.rhs);
1323             initsWhenTrue.andSet(initsWhenTrueLeft);
1324             uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1325             break;
1326         default:
1327             scanExpr(tree.lhs);
1328             scanExpr(tree.rhs);
1329         }
1330     }
1331 
1332     public void visitAnnotatedType(JCAnnotatedType tree) {
1333         // annotations don't get scanned
1334         tree.underlyingType.accept(this);
1335     }
1336 
1337     public void visitIdent(JCIdent tree) {
1338         if (tree.sym.kind == VAR) {
1339             checkInit(tree.pos(), (VarSymbol)tree.sym);
1340             referenced(tree.sym);
1341         }
1342     }
1343 
1344     void referenced(Symbol sym) {
1345         if (unrefdResources != null && unrefdResources.containsKey(sym)) {
1346             unrefdResources.remove(sym);
1347         }
1348     }
1349 
1350     public void visitTypeCast(JCTypeCast tree) {
1351         super.visitTypeCast(tree);
1352         if (!tree.type.isErroneous()
1353             && lint.isEnabled(Lint.LintCategory.CAST)
1354             && types.isSameType(tree.expr.type, tree.clazz.type)
1355             && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) {
1356             log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1357         }
1358     }
1359 
1360     public void visitTopLevel(JCCompilationUnit tree) {
1361         // Do nothing for TopLevel since each class is visited individually
1362     }
1363 
1364 /**************************************************************************
1365  * utility methods for ignoring type-annotated casts lint checking
1366  *************************************************************************/
1367     private static final boolean ignoreAnnotatedCasts = true;