src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 55306 ea43db53de91
parent 54321 c9a492ad1aed
child 59285 7799a51dbe30
equal deleted inserted replaced
55305:6e432194ee97 55306:ea43db53de91
     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));
  2786             }
  2825             }
  2787             super.visitTry(tree);
  2826             super.visitTry(tree);
  2788         }
  2827         }
  2789 
  2828 
  2790         @Override
  2829         @Override
  2791         public void visitBreak(JCBreak tree) {
  2830         public void visitYield(JCYield tree) {
  2792             if (tree.isValueBreak())
  2831             scan(tree.value);
  2793                 scan(tree.value);
       
  2794         }
  2832         }
  2795 
  2833 
  2796         public void visitModuleDef(JCModuleDecl tree) {
  2834         public void visitModuleDef(JCModuleDecl tree) {
  2797             // Do nothing for modules
  2835             // Do nothing for modules
  2798         }
  2836         }