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();
944 alive = true;
945 }
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 &&
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;
|
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 /** The list of unreferenced automatic resources.
269 */
270 List<Symbol> unrefdResources;
271
272 /** Set when processing a loop body the second time for DU analysis. */
273 boolean loopPassTwo = false;
274
275 /*-------------------- Environments ----------------------*/
276
277 /** A pending exit. These are the statements return, break, and
278 * continue. In addition, exception-throwing expressions or
279 * statements are put here when not known to be caught. This
280 * will typically result in an error unless it is within a
281 * try-finally whose finally block cannot complete normally.
282 */
283 static class PendingExit {
284 JCTree tree;
285 Bits inits;
286 Bits uninits;
287 Type thrown;
288 PendingExit(JCTree tree, Bits inits, Bits uninits) {
289 this.tree = tree;
290 this.inits = inits.dup();
291 this.uninits = uninits.dup();
948 alive = true;
949 }
950 alive |= resolveBreaks(tree, prevPendingExits);
951 nextadr = nextadrPrev;
952 }
953 // where
954 /** Add any variables defined in stats to inits and uninits. */
955 private static void addVars(List<JCStatement> stats, Bits inits,
956 Bits uninits) {
957 for (;stats.nonEmpty(); stats = stats.tail) {
958 JCTree stat = stats.head;
959 if (stat.getTag() == JCTree.VARDEF) {
960 int adr = ((JCVariableDecl) stat).sym.adr;
961 inits.excl(adr);
962 uninits.incl(adr);
963 }
964 }
965 }
966
967 public void visitTry(JCTry tree) {
968 unrefdResources = List.nil();
969 for (JCTree resource : tree.resources) {
970 if (resource instanceof JCVariableDecl) {
971 visitVarDef((JCVariableDecl) resource);
972 } else if (resource instanceof JCExpression) {
973 scanExpr((JCExpression) resource);
974 } else {
975 throw new AssertionError(tree); // parser error
976 }
977 }
978 List<Type> caughtPrev = caught;
979 List<Type> thrownPrev = thrown;
980 thrown = List.nil();
981 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
982 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
983 ((JCTypeDisjoint)l.head.param.vartype).components :
984 List.of(l.head.param.vartype);
985 for (JCExpression ct : subClauses) {
986 caught = chk.incl(ct.type, caught);
987 }
988 }
989 Bits uninitsTryPrev = uninitsTry;
990 ListBuffer<PendingExit> prevPendingExits = pendingExits;
991 pendingExits = new ListBuffer<PendingExit>();
992 Bits initsTry = inits.dup();
993 uninitsTry = uninits.dup();
994 for (JCTree resource : tree.resources) {
995 MethodSymbol closeMethod =
996 (MethodSymbol)resource.type.tsym.members().lookup(names.close).sym;
997 for (Type thrownType : closeMethod.getThrownTypes()) {
998 markThrown(tree.body, thrownType);
999 }
1000 }
1001 scanStat(tree.body);
1002 List<Type> thrownInTry = thrown;
1003 thrown = thrownPrev;
1004 caught = caughtPrev;
1005 boolean aliveEnd = alive;
1006 uninitsTry.andSet(uninits);
1007 Bits initsEnd = inits;
1008 Bits uninitsEnd = uninits;
1009 int nextadrCatch = nextadr;
1010
1011 if (unrefdResources.nonEmpty()) {
1012 for (List<JCTree> l = tree.resources; l.nonEmpty(); l = l.tail) {
1013 if (l.head instanceof JCVariableDecl) {
1014 JCVariableDecl v = (JCVariableDecl) l.head;
1015 if (unrefdResources.contains(v.sym)) {
1016 log.warning(v.pos(),
1017 "automatic.resource.not.referenced", v.sym);
1018 }
1019 }
1020 }
1021 }
1022
1023 List<Type> caughtInTry = List.nil();
1024 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1025 alive = true;
1026 JCVariableDecl param = l.head.param;
1027 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1028 ((JCTypeDisjoint)l.head.param.vartype).components :
1029 List.of(l.head.param.vartype);
1030 List<Type> ctypes = List.nil();
1031 List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1032 for (JCExpression ct : subClauses) {
1033 Type exc = ct.type;
1034 ctypes = ctypes.append(exc);
1035 if (types.isSameType(exc, syms.objectType))
1036 continue;
1037 if (chk.subset(exc, caughtInTry)) {
1038 log.error(l.head.pos(),
1039 "except.already.caught", exc);
1040 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1041 exc.tsym != syms.throwableType.tsym &&
1042 exc.tsym != syms.exceptionType.tsym &&
1309 Bits initsWhenTrueLeft = initsWhenTrue;
1310 Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1311 inits = initsWhenFalse;
1312 uninits = uninitsWhenFalse;
1313 scanCond(tree.rhs);
1314 initsWhenTrue.andSet(initsWhenTrueLeft);
1315 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1316 break;
1317 default:
1318 scanExpr(tree.lhs);
1319 scanExpr(tree.rhs);
1320 }
1321 }
1322
1323 public void visitAnnotatedType(JCAnnotatedType tree) {
1324 // annotations don't get scanned
1325 tree.underlyingType.accept(this);
1326 }
1327
1328 public void visitIdent(JCIdent tree) {
1329 if (tree.sym.kind == VAR) {
1330 checkInit(tree.pos(), (VarSymbol)tree.sym);
1331 referenced(tree.sym);
1332 }
1333 }
1334
1335 void referenced(Symbol sym) {
1336 if (unrefdResources != null && unrefdResources.contains(sym)) {
1337 ListBuffer<Symbol> lb = new ListBuffer<Symbol>();
1338 for (List<Symbol> l = unrefdResources; l.nonEmpty(); l = l.tail)
1339 if (l.head != sym)
1340 lb.add(l.head);
1341 unrefdResources = lb.toList();
1342 }
1343 }
1344
1345 public void visitTypeCast(JCTypeCast tree) {
1346 super.visitTypeCast(tree);
1347 if (!tree.type.isErroneous()
1348 && lint.isEnabled(Lint.LintCategory.CAST)
1349 && types.isSameType(tree.expr.type, tree.clazz.type)
1350 && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) {
1351 log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1352 }
1353 }
1354
1355 public void visitTopLevel(JCCompilationUnit tree) {
1356 // Do nothing for TopLevel since each class is visited individually
1357 }
1358
1359 /**************************************************************************
1360 * utility methods for ignoring type-annotated casts lint checking
1361 *************************************************************************/
1362 private static final boolean ignoreAnnotatedCasts = true;
|