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;
|