langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 10950 e87b50888909
parent 9601 a1b1716231ca
child 12333 7b02d0529a97
equal deleted inserted replaced
10949:42f7cc0468dd 10950:e87b50888909
    38 
    38 
    39 import com.sun.tools.javac.code.Symbol.*;
    39 import com.sun.tools.javac.code.Symbol.*;
    40 import com.sun.tools.javac.tree.JCTree.*;
    40 import com.sun.tools.javac.tree.JCTree.*;
    41 
    41 
    42 import static com.sun.tools.javac.code.Flags.*;
    42 import static com.sun.tools.javac.code.Flags.*;
       
    43 import static com.sun.tools.javac.code.Flags.BLOCK;
    43 import static com.sun.tools.javac.code.Kinds.*;
    44 import static com.sun.tools.javac.code.Kinds.*;
    44 import static com.sun.tools.javac.code.TypeTags.*;
    45 import static com.sun.tools.javac.code.TypeTags.*;
       
    46 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    45 
    47 
    46 /** This pass implements dataflow analysis for Java programs.
    48 /** This pass implements dataflow analysis for Java programs.
    47  *  Liveness analysis checks that every statement is reachable.
    49  *  Liveness analysis checks that every statement is reachable.
    48  *  Exception analysis ensures that every checked exception that is
    50  *  Exception analysis ensures that every checked exception that is
    49  *  thrown is declared or caught.  Definite assignment analysis
    51  *  thrown is declared or caught.  Definite assignment analysis
   319             if (classDef != null &&
   321             if (classDef != null &&
   320                 classDef.pos == exit.tree.pos) {
   322                 classDef.pos == exit.tree.pos) {
   321                 log.error(exit.tree.pos(),
   323                 log.error(exit.tree.pos(),
   322                         "unreported.exception.default.constructor",
   324                         "unreported.exception.default.constructor",
   323                         exit.thrown);
   325                         exit.thrown);
   324             } else if (exit.tree.getTag() == JCTree.VARDEF &&
   326             } else if (exit.tree.hasTag(VARDEF) &&
   325                     ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
   327                     ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
   326                 log.error(exit.tree.pos(),
   328                 log.error(exit.tree.pos(),
   327                         "unreported.exception.implicit.close",
   329                         "unreported.exception.implicit.close",
   328                         exit.thrown,
   330                         exit.thrown,
   329                         ((JCVariableDecl)exit.tree).sym.name);
   331                         ((JCVariableDecl)exit.tree).sym.name);
   414      *  C.this.name, and tree represents a trackable variable,
   416      *  C.this.name, and tree represents a trackable variable,
   415      *  record an initialization of the variable.
   417      *  record an initialization of the variable.
   416      */
   418      */
   417     void letInit(JCTree tree) {
   419     void letInit(JCTree tree) {
   418         tree = TreeInfo.skipParens(tree);
   420         tree = TreeInfo.skipParens(tree);
   419         if (tree.getTag() == JCTree.IDENT || tree.getTag() == JCTree.SELECT) {
   421         if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
   420             Symbol sym = TreeInfo.symbol(tree);
   422             Symbol sym = TreeInfo.symbol(tree);
   421             if (sym.kind == VAR) {
   423             if (sym.kind == VAR) {
   422                 letInit(tree.pos(), (VarSymbol)sym);
   424                 letInit(tree.pos(), (VarSymbol)sym);
   423             }
   425             }
   424         }
   426         }
   450         boolean result = false;
   452         boolean result = false;
   451         List<PendingExit> exits = pendingExits.toList();
   453         List<PendingExit> exits = pendingExits.toList();
   452         pendingExits = oldPendingExits;
   454         pendingExits = oldPendingExits;
   453         for (; exits.nonEmpty(); exits = exits.tail) {
   455         for (; exits.nonEmpty(); exits = exits.tail) {
   454             PendingExit exit = exits.head;
   456             PendingExit exit = exits.head;
   455             if (exit.tree.getTag() == JCTree.BREAK &&
   457             if (exit.tree.hasTag(BREAK) &&
   456                 ((JCBreak) exit.tree).target == tree) {
   458                 ((JCBreak) exit.tree).target == tree) {
   457                 inits.andSet(exit.inits);
   459                 inits.andSet(exit.inits);
   458                 uninits.andSet(exit.uninits);
   460                 uninits.andSet(exit.uninits);
   459                 result = true;
   461                 result = true;
   460             } else {
   462             } else {
   469         boolean result = false;
   471         boolean result = false;
   470         List<PendingExit> exits = pendingExits.toList();
   472         List<PendingExit> exits = pendingExits.toList();
   471         pendingExits = new ListBuffer<PendingExit>();
   473         pendingExits = new ListBuffer<PendingExit>();
   472         for (; exits.nonEmpty(); exits = exits.tail) {
   474         for (; exits.nonEmpty(); exits = exits.tail) {
   473             PendingExit exit = exits.head;
   475             PendingExit exit = exits.head;
   474             if (exit.tree.getTag() == JCTree.CONTINUE &&
   476             if (exit.tree.hasTag(CONTINUE) &&
   475                 ((JCContinue) exit.tree).target == tree) {
   477                 ((JCContinue) exit.tree).target == tree) {
   476                 inits.andSet(exit.inits);
   478                 inits.andSet(exit.inits);
   477                 uninits.andSet(exit.uninits);
   479                 uninits.andSet(exit.uninits);
   478                 result = true;
   480                 result = true;
   479             } else {
   481             } else {
   515 
   517 
   516     /** Analyze a definition.
   518     /** Analyze a definition.
   517      */
   519      */
   518     void scanDef(JCTree tree) {
   520     void scanDef(JCTree tree) {
   519         scanStat(tree);
   521         scanStat(tree);
   520         if (tree != null && tree.getTag() == JCTree.BLOCK && !alive) {
   522         if (tree != null && tree.hasTag(JCTree.Tag.BLOCK) && !alive) {
   521             log.error(tree.pos(),
   523             log.error(tree.pos(),
   522                       "initializer.must.be.able.to.complete.normally");
   524                       "initializer.must.be.able.to.complete.normally");
   523         }
   525         }
   524     }
   526     }
   525 
   527 
   526     /** Analyze a statement. Check that statement is reachable.
   528     /** Analyze a statement. Check that statement is reachable.
   527      */
   529      */
   528     void scanStat(JCTree tree) {
   530     void scanStat(JCTree tree) {
   529         if (!alive && tree != null) {
   531         if (!alive && tree != null) {
   530             log.error(tree.pos(), "unreachable.stmt");
   532             log.error(tree.pos(), "unreachable.stmt");
   531             if (tree.getTag() != JCTree.SKIP) alive = true;
   533             if (!tree.hasTag(SKIP)) alive = true;
   532         }
   534         }
   533         scan(tree);
   535         scan(tree);
   534     }
   536     }
   535 
   537 
   536     /** Analyze list of statements.
   538     /** Analyze list of statements.
   612         lint = lint.augment(tree.sym.attributes_field);
   614         lint = lint.augment(tree.sym.attributes_field);
   613 
   615 
   614         try {
   616         try {
   615             // define all the static fields
   617             // define all the static fields
   616             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   618             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   617                 if (l.head.getTag() == JCTree.VARDEF) {
   619                 if (l.head.hasTag(VARDEF)) {
   618                     JCVariableDecl def = (JCVariableDecl)l.head;
   620                     JCVariableDecl def = (JCVariableDecl)l.head;
   619                     if ((def.mods.flags & STATIC) != 0) {
   621                     if ((def.mods.flags & STATIC) != 0) {
   620                         VarSymbol sym = def.sym;
   622                         VarSymbol sym = def.sym;
   621                         if (trackable(sym))
   623                         if (trackable(sym))
   622                             newVar(sym);
   624                             newVar(sym);
   624                 }
   626                 }
   625             }
   627             }
   626 
   628 
   627             // process all the static initializers
   629             // process all the static initializers
   628             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   630             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   629                 if (l.head.getTag() != JCTree.METHODDEF &&
   631                 if (!l.head.hasTag(METHODDEF) &&
   630                     (TreeInfo.flags(l.head) & STATIC) != 0) {
   632                     (TreeInfo.flags(l.head) & STATIC) != 0) {
   631                     scanDef(l.head);
   633                     scanDef(l.head);
   632                     errorUncaught();
   634                     errorUncaught();
   633                 }
   635                 }
   634             }
   636             }
   651                 }
   653                 }
   652             }
   654             }
   653 
   655 
   654             // define all the instance fields
   656             // define all the instance fields
   655             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   657             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   656                 if (l.head.getTag() == JCTree.VARDEF) {
   658                 if (l.head.hasTag(VARDEF)) {
   657                     JCVariableDecl def = (JCVariableDecl)l.head;
   659                     JCVariableDecl def = (JCVariableDecl)l.head;
   658                     if ((def.mods.flags & STATIC) == 0) {
   660                     if ((def.mods.flags & STATIC) == 0) {
   659                         VarSymbol sym = def.sym;
   661                         VarSymbol sym = def.sym;
   660                         if (trackable(sym))
   662                         if (trackable(sym))
   661                             newVar(sym);
   663                             newVar(sym);
   663                 }
   665                 }
   664             }
   666             }
   665 
   667 
   666             // process all the instance initializers
   668             // process all the instance initializers
   667             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   669             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   668                 if (l.head.getTag() != JCTree.METHODDEF &&
   670                 if (!l.head.hasTag(METHODDEF) &&
   669                     (TreeInfo.flags(l.head) & STATIC) == 0) {
   671                     (TreeInfo.flags(l.head) & STATIC) == 0) {
   670                     scanDef(l.head);
   672                     scanDef(l.head);
   671                     errorUncaught();
   673                     errorUncaught();
   672                 }
   674                 }
   673             }
   675             }
   689                 thrownPrev = chk.union(thrown, thrownPrev);
   691                 thrownPrev = chk.union(thrown, thrownPrev);
   690             }
   692             }
   691 
   693 
   692             // process all the methods
   694             // process all the methods
   693             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   695             for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
   694                 if (l.head.getTag() == JCTree.METHODDEF) {
   696                 if (l.head.hasTag(METHODDEF)) {
   695                     scan(l.head);
   697                     scan(l.head);
   696                     errorUncaught();
   698                     errorUncaught();
   697                 }
   699                 }
   698             }
   700             }
   699 
   701 
   758             pendingExits = new ListBuffer<PendingExit>();
   760             pendingExits = new ListBuffer<PendingExit>();
   759             while (exits.nonEmpty()) {
   761             while (exits.nonEmpty()) {
   760                 PendingExit exit = exits.head;
   762                 PendingExit exit = exits.head;
   761                 exits = exits.tail;
   763                 exits = exits.tail;
   762                 if (exit.thrown == null) {
   764                 if (exit.thrown == null) {
   763                     Assert.check(exit.tree.getTag() == JCTree.RETURN);
   765                     Assert.check(exit.tree.hasTag(RETURN));
   764                     if (isInitialConstructor) {
   766                     if (isInitialConstructor) {
   765                         inits = exit.inits;
   767                         inits = exit.inits;
   766                         for (int i = firstadr; i < nextadr; i++)
   768                         for (int i = firstadr; i < nextadr; i++)
   767                             checkInit(exit.tree.pos(), vars[i]);
   769                             checkInit(exit.tree.pos(), vars[i]);
   768                     }
   770                     }
   987         /** Add any variables defined in stats to inits and uninits. */
   989         /** Add any variables defined in stats to inits and uninits. */
   988         private static void addVars(List<JCStatement> stats, Bits inits,
   990         private static void addVars(List<JCStatement> stats, Bits inits,
   989                                     Bits uninits) {
   991                                     Bits uninits) {
   990             for (;stats.nonEmpty(); stats = stats.tail) {
   992             for (;stats.nonEmpty(); stats = stats.tail) {
   991                 JCTree stat = stats.head;
   993                 JCTree stat = stats.head;
   992                 if (stat.getTag() == JCTree.VARDEF) {
   994                 if (stat.hasTag(VARDEF)) {
   993                     int adr = ((JCVariableDecl) stat).sym.adr;
   995                     int adr = ((JCVariableDecl) stat).sym.adr;
   994                     inits.excl(adr);
   996                     inits.excl(adr);
   995                     uninits.incl(adr);
   997                     uninits.incl(adr);
   996                 }
   998                 }
   997             }
   999             }
  1344         letInit(tree.lhs);
  1346         letInit(tree.lhs);
  1345     }
  1347     }
  1346 
  1348 
  1347     public void visitUnary(JCUnary tree) {
  1349     public void visitUnary(JCUnary tree) {
  1348         switch (tree.getTag()) {
  1350         switch (tree.getTag()) {
  1349         case JCTree.NOT:
  1351         case NOT:
  1350             scanCond(tree.arg);
  1352             scanCond(tree.arg);
  1351             Bits t = initsWhenFalse;
  1353             Bits t = initsWhenFalse;
  1352             initsWhenFalse = initsWhenTrue;
  1354             initsWhenFalse = initsWhenTrue;
  1353             initsWhenTrue = t;
  1355             initsWhenTrue = t;
  1354             t = uninitsWhenFalse;
  1356             t = uninitsWhenFalse;
  1355             uninitsWhenFalse = uninitsWhenTrue;
  1357             uninitsWhenFalse = uninitsWhenTrue;
  1356             uninitsWhenTrue = t;
  1358             uninitsWhenTrue = t;
  1357             break;
  1359             break;
  1358         case JCTree.PREINC: case JCTree.POSTINC:
  1360         case PREINC: case POSTINC:
  1359         case JCTree.PREDEC: case JCTree.POSTDEC:
  1361         case PREDEC: case POSTDEC:
  1360             scanExpr(tree.arg);
  1362             scanExpr(tree.arg);
  1361             letInit(tree.arg);
  1363             letInit(tree.arg);
  1362             break;
  1364             break;
  1363         default:
  1365         default:
  1364             scanExpr(tree.arg);
  1366             scanExpr(tree.arg);
  1365         }
  1367         }
  1366     }
  1368     }
  1367 
  1369 
  1368     public void visitBinary(JCBinary tree) {
  1370     public void visitBinary(JCBinary tree) {
  1369         switch (tree.getTag()) {
  1371         switch (tree.getTag()) {
  1370         case JCTree.AND:
  1372         case AND:
  1371             scanCond(tree.lhs);
  1373             scanCond(tree.lhs);
  1372             Bits initsWhenFalseLeft = initsWhenFalse;
  1374             Bits initsWhenFalseLeft = initsWhenFalse;
  1373             Bits uninitsWhenFalseLeft = uninitsWhenFalse;
  1375             Bits uninitsWhenFalseLeft = uninitsWhenFalse;
  1374             inits = initsWhenTrue;
  1376             inits = initsWhenTrue;
  1375             uninits = uninitsWhenTrue;
  1377             uninits = uninitsWhenTrue;
  1376             scanCond(tree.rhs);
  1378             scanCond(tree.rhs);
  1377             initsWhenFalse.andSet(initsWhenFalseLeft);
  1379             initsWhenFalse.andSet(initsWhenFalseLeft);
  1378             uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
  1380             uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
  1379             break;
  1381             break;
  1380         case JCTree.OR:
  1382         case OR:
  1381             scanCond(tree.lhs);
  1383             scanCond(tree.lhs);
  1382             Bits initsWhenTrueLeft = initsWhenTrue;
  1384             Bits initsWhenTrueLeft = initsWhenTrue;
  1383             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
  1385             Bits uninitsWhenTrueLeft = uninitsWhenTrue;
  1384             inits = initsWhenFalse;
  1386             inits = initsWhenFalse;
  1385             uninits = uninitsWhenFalse;
  1387             uninits = uninitsWhenFalse;
  1416     }
  1418     }
  1417     //where
  1419     //where
  1418         private boolean is292targetTypeCast(JCTypeCast tree) {
  1420         private boolean is292targetTypeCast(JCTypeCast tree) {
  1419             boolean is292targetTypeCast = false;
  1421             boolean is292targetTypeCast = false;
  1420             JCExpression expr = TreeInfo.skipParens(tree.expr);
  1422             JCExpression expr = TreeInfo.skipParens(tree.expr);
  1421             if (expr.getTag() == JCTree.APPLY) {
  1423             if (expr.hasTag(APPLY)) {
  1422                 JCMethodInvocation apply = (JCMethodInvocation)expr;
  1424                 JCMethodInvocation apply = (JCMethodInvocation)expr;
  1423                 Symbol sym = TreeInfo.symbol(apply.meth);
  1425                 Symbol sym = TreeInfo.symbol(apply.meth);
  1424                 is292targetTypeCast = sym != null &&
  1426                 is292targetTypeCast = sym != null &&
  1425                     sym.kind == MTH &&
  1427                     sym.kind == MTH &&
  1426                     (sym.flags() & POLYMORPHIC_SIGNATURE) != 0;
  1428                     (sym.flags() & POLYMORPHIC_SIGNATURE) != 0;