1 /* |
1 /* |
2 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
312 CONTINUE(JCTree.Tag.CONTINUE) { |
312 CONTINUE(JCTree.Tag.CONTINUE) { |
313 @Override |
313 @Override |
314 JCTree getTarget(JCTree tree) { |
314 JCTree getTarget(JCTree tree) { |
315 return ((JCContinue)tree).target; |
315 return ((JCContinue)tree).target; |
316 } |
316 } |
|
317 }, |
|
318 YIELD(JCTree.Tag.YIELD) { |
|
319 @Override |
|
320 JCTree getTarget(JCTree tree) { |
|
321 return ((JCYield)tree).target; |
|
322 } |
317 }; |
323 }; |
318 |
324 |
319 final JCTree.Tag treeTag; |
325 final JCTree.Tag treeTag; |
320 |
326 |
321 private JumpKind(Tag treeTag) { |
327 private JumpKind(Tag treeTag) { |
384 /** Resolve all breaks of this statement. */ |
390 /** Resolve all breaks of this statement. */ |
385 Liveness resolveBreaks(JCTree tree, ListBuffer<PendingExit> oldPendingExits) { |
391 Liveness resolveBreaks(JCTree tree, ListBuffer<PendingExit> oldPendingExits) { |
386 return resolveJump(tree, oldPendingExits, JumpKind.BREAK); |
392 return resolveJump(tree, oldPendingExits, JumpKind.BREAK); |
387 } |
393 } |
388 |
394 |
|
395 /** Resolve all yields of this statement. */ |
|
396 Liveness resolveYields(JCTree tree, ListBuffer<PendingExit> oldPendingExits) { |
|
397 return resolveJump(tree, oldPendingExits, JumpKind.YIELD); |
|
398 } |
|
399 |
389 @Override |
400 @Override |
390 public void scan(JCTree tree) { |
401 public void scan(JCTree tree) { |
391 if (tree != null && ( |
402 if (tree != null && ( |
392 tree.type == null || |
403 tree.type == null || |
393 tree.type != Type.stuckType)) { |
404 tree.type != Type.stuckType)) { |
398 public void visitPackageDef(JCPackageDecl tree) { |
409 public void visitPackageDef(JCPackageDecl tree) { |
399 // Do nothing for PackageDecl |
410 // Do nothing for PackageDecl |
400 } |
411 } |
401 |
412 |
402 protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) { |
413 protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) { |
403 JCBreak brk = make.at(Position.NOPOS).Break(null); |
414 if (swtch.hasTag(SWITCH_EXPRESSION)) { |
404 brk.target = swtch; |
415 JCYield brk = make.at(Position.NOPOS).Yield(null); |
405 scan(brk); |
416 brk.target = swtch; |
|
417 scan(brk); |
|
418 } else { |
|
419 JCBreak brk = make.at(Position.NOPOS).Break(null); |
|
420 brk.target = swtch; |
|
421 scan(brk); |
|
422 } |
406 } |
423 } |
407 } |
424 } |
408 |
425 |
409 /** |
426 /** |
410 * This pass implements the first step of the dataflow analysis, namely |
427 * This pass implements the first step of the dataflow analysis, namely |
515 List<PendingExit> exits = pendingExits.toList(); |
532 List<PendingExit> exits = pendingExits.toList(); |
516 pendingExits = new ListBuffer<>(); |
533 pendingExits = new ListBuffer<>(); |
517 while (exits.nonEmpty()) { |
534 while (exits.nonEmpty()) { |
518 PendingExit exit = exits.head; |
535 PendingExit exit = exits.head; |
519 exits = exits.tail; |
536 exits = exits.tail; |
520 Assert.check(exit.tree.hasTag(RETURN)); |
537 Assert.check(exit.tree.hasTag(RETURN) || |
|
538 log.hasErrorOn(exit.tree.pos())); |
521 } |
539 } |
522 } finally { |
540 } finally { |
523 lint = lintPrev; |
541 lint = lintPrev; |
524 } |
542 } |
525 } |
543 } |
675 } |
693 } |
676 if ((constants == null || !constants.isEmpty()) && !hasDefault) { |
694 if ((constants == null || !constants.isEmpty()) && !hasDefault) { |
677 log.error(tree, Errors.NotExhaustive); |
695 log.error(tree, Errors.NotExhaustive); |
678 } |
696 } |
679 alive = prevAlive; |
697 alive = prevAlive; |
680 alive = alive.or(resolveBreaks(tree, prevPendingExits)); |
698 alive = alive.or(resolveYields(tree, prevPendingExits)); |
681 } |
699 } |
682 |
700 |
683 public void visitTry(JCTry tree) { |
701 public void visitTry(JCTry tree) { |
684 ListBuffer<PendingExit> prevPendingExits = pendingExits; |
702 ListBuffer<PendingExit> prevPendingExits = pendingExits; |
685 pendingExits = new ListBuffer<>(); |
703 pendingExits = new ListBuffer<>(); |
743 alive = Liveness.ALIVE; |
761 alive = Liveness.ALIVE; |
744 } |
762 } |
745 } |
763 } |
746 |
764 |
747 public void visitBreak(JCBreak tree) { |
765 public void visitBreak(JCBreak tree) { |
748 if (tree.isValueBreak()) |
766 recordExit(new PendingExit(tree)); |
749 scan(tree.value); |
767 } |
|
768 |
|
769 @Override |
|
770 public void visitYield(JCYield tree) { |
|
771 scan(tree.value); |
750 recordExit(new PendingExit(tree)); |
772 recordExit(new PendingExit(tree)); |
751 } |
773 } |
752 |
774 |
753 public void visitContinue(JCContinue tree) { |
775 public void visitContinue(JCContinue tree) { |
754 recordExit(new PendingExit(tree)); |
776 recordExit(new PendingExit(tree)); |
1030 pendingExits = new ListBuffer<>(); |
1052 pendingExits = new ListBuffer<>(); |
1031 while (exits.nonEmpty()) { |
1053 while (exits.nonEmpty()) { |
1032 PendingExit exit = exits.head; |
1054 PendingExit exit = exits.head; |
1033 exits = exits.tail; |
1055 exits = exits.tail; |
1034 if (!(exit instanceof ThrownPendingExit)) { |
1056 if (!(exit instanceof ThrownPendingExit)) { |
1035 Assert.check(exit.tree.hasTag(RETURN)); |
1057 Assert.check(exit.tree.hasTag(RETURN) || |
|
1058 log.hasErrorOn(exit.tree.pos())); |
1036 } else { |
1059 } else { |
1037 // uncaught throws will be reported later |
1060 // uncaught throws will be reported later |
1038 pendingExits.append(exit); |
1061 pendingExits.append(exit); |
1039 } |
1062 } |
1040 } |
1063 } |
1124 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { |
1147 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { |
1125 JCCase c = l.head; |
1148 JCCase c = l.head; |
1126 scan(c.pats); |
1149 scan(c.pats); |
1127 scan(c.stats); |
1150 scan(c.stats); |
1128 } |
1151 } |
1129 resolveBreaks(tree, prevPendingExits); |
1152 if (tree.hasTag(SWITCH_EXPRESSION)) { |
|
1153 resolveYields(tree, prevPendingExits); |
|
1154 } else { |
|
1155 resolveBreaks(tree, prevPendingExits); |
|
1156 } |
1130 } |
1157 } |
1131 |
1158 |
1132 public void visitTry(JCTry tree) { |
1159 public void visitTry(JCTry tree) { |
1133 List<Type> caughtPrev = caught; |
1160 List<Type> caughtPrev = caught; |
1134 List<Type> thrownPrev = thrown; |
1161 List<Type> thrownPrev = thrown; |
1265 return exc.tsym == syms.throwableType.tsym || |
1292 return exc.tsym == syms.throwableType.tsym || |
1266 exc.tsym == syms.exceptionType.tsym; |
1293 exc.tsym == syms.exceptionType.tsym; |
1267 } |
1294 } |
1268 |
1295 |
1269 public void visitBreak(JCBreak tree) { |
1296 public void visitBreak(JCBreak tree) { |
1270 if (tree.isValueBreak()) |
1297 recordExit(new PendingExit(tree)); |
1271 scan(tree.value); |
1298 } |
|
1299 |
|
1300 public void visitYield(JCYield tree) { |
|
1301 scan(tree.value); |
1272 recordExit(new PendingExit(tree)); |
1302 recordExit(new PendingExit(tree)); |
1273 } |
1303 } |
1274 |
1304 |
1275 public void visitContinue(JCContinue tree) { |
1305 public void visitContinue(JCContinue tree) { |
1276 recordExit(new PendingExit(tree)); |
1306 recordExit(new PendingExit(tree)); |
1355 pendingExits = new ListBuffer<>(); |
1385 pendingExits = new ListBuffer<>(); |
1356 while (exits.nonEmpty()) { |
1386 while (exits.nonEmpty()) { |
1357 PendingExit exit = exits.head; |
1387 PendingExit exit = exits.head; |
1358 exits = exits.tail; |
1388 exits = exits.tail; |
1359 if (!(exit instanceof ThrownPendingExit)) { |
1389 if (!(exit instanceof ThrownPendingExit)) { |
1360 Assert.check(exit.tree.hasTag(RETURN)); |
1390 Assert.check(exit.tree.hasTag(RETURN) || |
|
1391 log.hasErrorOn(exit.tree.pos())); |
1361 } else { |
1392 } else { |
1362 // uncaught throws will be reported later |
1393 // uncaught throws will be reported later |
1363 pendingExits.append(exit); |
1394 pendingExits.append(exit); |
1364 } |
1395 } |
1365 } |
1396 } |
1975 List<PendingExit> exits = pendingExits.toList(); |
2006 List<PendingExit> exits = pendingExits.toList(); |
1976 pendingExits = new ListBuffer<>(); |
2007 pendingExits = new ListBuffer<>(); |
1977 while (exits.nonEmpty()) { |
2008 while (exits.nonEmpty()) { |
1978 PendingExit exit = exits.head; |
2009 PendingExit exit = exits.head; |
1979 exits = exits.tail; |
2010 exits = exits.tail; |
1980 Assert.check(exit.tree.hasTag(RETURN), exit.tree); |
2011 Assert.check(exit.tree.hasTag(RETURN) || |
|
2012 log.hasErrorOn(exit.tree.pos()), |
|
2013 exit.tree); |
1981 if (isInitialConstructor) { |
2014 if (isInitialConstructor) { |
1982 Assert.check(exit instanceof AssignPendingExit); |
2015 Assert.check(exit instanceof AssignPendingExit); |
1983 inits.assign(((AssignPendingExit) exit).exit_inits); |
2016 inits.assign(((AssignPendingExit) exit).exit_inits); |
1984 for (int i = firstadr; i < nextadr; i++) { |
2017 for (int i = firstadr; i < nextadr; i++) { |
1985 checkInit(exit.tree.pos(), vardecls[i].sym); |
2018 checkInit(exit.tree.pos(), vardecls[i].sym); |
2230 markDead(); |
2263 markDead(); |
2231 } else { |
2264 } else { |
2232 inits.andSet(initsSwitch); |
2265 inits.andSet(initsSwitch); |
2233 } |
2266 } |
2234 } |
2267 } |
2235 resolveBreaks(tree, prevPendingExits); |
2268 if (tree.hasTag(SWITCH_EXPRESSION)) { |
|
2269 resolveYields(tree, prevPendingExits); |
|
2270 } else { |
|
2271 resolveBreaks(tree, prevPendingExits); |
|
2272 } |
2236 nextadr = nextadrPrev; |
2273 nextadr = nextadrPrev; |
2237 } |
2274 } |
2238 // where |
2275 // where |
2239 /** Add any variables defined in stats to inits and uninits. */ |
2276 /** Add any variables defined in stats to inits and uninits. */ |
2240 private void addVars(List<JCStatement> stats, final Bits inits, |
2277 private void addVars(List<JCStatement> stats, final Bits inits, |
2395 } |
2432 } |
2396 } |
2433 } |
2397 |
2434 |
2398 @Override |
2435 @Override |
2399 public void visitBreak(JCBreak tree) { |
2436 public void visitBreak(JCBreak tree) { |
2400 if (tree.isValueBreak()) { |
2437 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2401 if (tree.target.hasTag(SWITCH_EXPRESSION)) { |
2438 } |
2402 JCSwitchExpression expr = (JCSwitchExpression) tree.target; |
2439 |
2403 if (expr.type.hasTag(BOOLEAN)) { |
2440 @Override |
2404 scanCond(tree.value); |
2441 public void visitYield(JCYield tree) { |
2405 Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue); |
2442 JCSwitchExpression expr = (JCSwitchExpression) tree.target; |
2406 Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse); |
2443 if (expr != null && expr.type.hasTag(BOOLEAN)) { |
2407 Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue); |
2444 scanCond(tree.value); |
2408 Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse); |
2445 Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue); |
2409 PendingExit exit = new PendingExit(tree) { |
2446 Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse); |
2410 @Override |
2447 Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue); |
2411 void resolveJump() { |
2448 Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse); |
2412 if (!inits.isReset()) { |
2449 PendingExit exit = new PendingExit(tree) { |
2413 split(true); |
2450 @Override |
2414 } |
2451 void resolveJump() { |
2415 initsWhenTrue.andSet(initsAfterBreakWhenTrue); |
2452 if (!inits.isReset()) { |
2416 initsWhenFalse.andSet(initsAfterBreakWhenFalse); |
2453 split(true); |
2417 uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue); |
2454 } |
2418 uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse); |
2455 initsWhenTrue.andSet(initsAfterBreakWhenTrue); |
2419 } |
2456 initsWhenFalse.andSet(initsAfterBreakWhenFalse); |
2420 }; |
2457 uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue); |
2421 merge(); |
2458 uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse); |
2422 recordExit(exit); |
2459 } |
2423 return ; |
2460 }; |
2424 } |
2461 merge(); |
2425 } |
2462 recordExit(exit); |
|
2463 return ; |
|
2464 } else { |
2426 scan(tree.value); |
2465 scan(tree.value); |
2427 } |
2466 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2428 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2467 } |
2429 } |
2468 } |
2430 |
2469 |
2431 @Override |
2470 @Override |
2432 public void visitContinue(JCContinue tree) { |
2471 public void visitContinue(JCContinue tree) { |
2433 recordExit(new AssignPendingExit(tree, inits, uninits)); |
2472 recordExit(new AssignPendingExit(tree, inits, uninits)); |