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 topCloseMethod = (MethodSymbol)syms.autoCloseableType.tsym.members().lookup(names.close).sym;
996 MethodSymbol closeMethod = types.implementation(topCloseMethod, resource.type.tsym, types, true);
997
998 for (Type thrownType : closeMethod.getThrownTypes()) {
999 markThrown(tree.body, thrownType);
1000 }
1001 }
1002 scanStat(tree.body);
1003 List<Type> thrownInTry = thrown;
1004 thrown = thrownPrev;
1005 caught = caughtPrev;
1006 boolean aliveEnd = alive;
1007 uninitsTry.andSet(uninits);
1008 Bits initsEnd = inits;
1009 Bits uninitsEnd = uninits;
1010 int nextadrCatch = nextadr;
1011
1012 if (unrefdResources.nonEmpty()) {
1013 for (List<JCTree> l = tree.resources; l.nonEmpty(); l = l.tail) {
1014 if (l.head instanceof JCVariableDecl) {
1015 JCVariableDecl v = (JCVariableDecl) l.head;
1016 if (unrefdResources.contains(v.sym)) {
1017 log.warning(v.pos(),
1018 "automatic.resource.not.referenced", v.sym);
1019 }
1020 }
1021 }
1022 }
1023
1024 List<Type> caughtInTry = List.nil();
1025 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
1026 alive = true;
1027 JCVariableDecl param = l.head.param;
1028 List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ?
1029 ((JCTypeDisjoint)l.head.param.vartype).components :
1030 List.of(l.head.param.vartype);
1031 List<Type> ctypes = List.nil();
1032 List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
1033 for (JCExpression ct : subClauses) {
1034 Type exc = ct.type;
1035 ctypes = ctypes.append(exc);
1036 if (types.isSameType(exc, syms.objectType))
1037 continue;
1038 if (chk.subset(exc, caughtInTry)) {
1039 log.error(l.head.pos(),
1040 "except.already.caught", exc);
1041 } else if (!chk.isUnchecked(l.head.pos(), exc) &&
1042 exc.tsym != syms.throwableType.tsym &&
1043 exc.tsym != syms.exceptionType.tsym &&
1310 Bits initsWhenTrueLeft = initsWhenTrue;
1311 Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1312 inits = initsWhenFalse;
1313 uninits = uninitsWhenFalse;
1314 scanCond(tree.rhs);
1315 initsWhenTrue.andSet(initsWhenTrueLeft);
1316 uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1317 break;
1318 default:
1319 scanExpr(tree.lhs);
1320 scanExpr(tree.rhs);
1321 }
1322 }
1323
1324 public void visitAnnotatedType(JCAnnotatedType tree) {
1325 // annotations don't get scanned
1326 tree.underlyingType.accept(this);
1327 }
1328
1329 public void visitIdent(JCIdent tree) {
1330 if (tree.sym.kind == VAR) {
1331 checkInit(tree.pos(), (VarSymbol)tree.sym);
1332 referenced(tree.sym);
1333 }
1334 }
1335
1336 void referenced(Symbol sym) {
1337 if (unrefdResources != null && unrefdResources.contains(sym)) {
1338 ListBuffer<Symbol> lb = new ListBuffer<Symbol>();
1339 for (List<Symbol> l = unrefdResources; l.nonEmpty(); l = l.tail)
1340 if (l.head != sym)
1341 lb.add(l.head);
1342 unrefdResources = lb.toList();
1343 }
1344 }
1345
1346 public void visitTypeCast(JCTypeCast tree) {
1347 super.visitTypeCast(tree);
1348 if (!tree.type.isErroneous()
1349 && lint.isEnabled(Lint.LintCategory.CAST)
1350 && types.isSameType(tree.expr.type, tree.clazz.type)
1351 && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))) {
1352 log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1353 }
1354 }
1355
1356 public void visitTopLevel(JCCompilationUnit tree) {
1357 // Do nothing for TopLevel since each class is visited individually
1358 }
1359
1360 /**************************************************************************
1361 * utility methods for ignoring type-annotated casts lint checking
1362 *************************************************************************/
1363 private static final boolean ignoreAnnotatedCasts = true;
|