Source Code Cross Referenced for Flow.java in  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » javac » comp » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules com.sun » tools » com.sun.tools.javac.comp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        //todo: one might eliminate uninits.andSets when monotonic
0027:        package com.sun.tools.javac.comp;
0028:
0029:        import com.sun.tools.javac.code.*;
0030:        import com.sun.tools.javac.tree.*;
0031:        import com.sun.tools.javac.util.*;
0032:        import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
0033:
0034:        import com.sun.tools.javac.code.Symbol.*;
0035:        import com.sun.tools.javac.tree.JCTree.*;
0036:
0037:        import static com.sun.tools.javac.code.Flags.*;
0038:        import static com.sun.tools.javac.code.Kinds.*;
0039:        import static com.sun.tools.javac.code.TypeTags.*;
0040:
0041:        /** This pass implements dataflow analysis for Java programs.
0042:         *  Liveness analysis checks that every statement is reachable.
0043:         *  Exception analysis ensures that every checked exception that is
0044:         *  thrown is declared or caught.  Definite assignment analysis
0045:         *  ensures that each variable is assigned when used.  Definite
0046:         *  unassignment analysis ensures that no final variable is assigned
0047:         *  more than once.
0048:         *
0049:         *  <p>The second edition of the JLS has a number of problems in the
0050:         *  specification of these flow analysis problems. This implementation
0051:         *  attempts to address those issues.
0052:         *
0053:         *  <p>First, there is no accommodation for a finally clause that cannot
0054:         *  complete normally. For liveness analysis, an intervening finally
0055:         *  clause can cause a break, continue, or return not to reach its
0056:         *  target.  For exception analysis, an intervening finally clause can
0057:         *  cause any exception to be "caught".  For DA/DU analysis, the finally
0058:         *  clause can prevent a transfer of control from propagating DA/DU
0059:         *  state to the target.  In addition, code in the finally clause can
0060:         *  affect the DA/DU status of variables.
0061:         *
0062:         *  <p>For try statements, we introduce the idea of a variable being
0063:         *  definitely unassigned "everywhere" in a block.  A variable V is
0064:         *  "unassigned everywhere" in a block iff it is unassigned at the
0065:         *  beginning of the block and there is no reachable assignment to V
0066:         *  in the block.  An assignment V=e is reachable iff V is not DA
0067:         *  after e.  Then we can say that V is DU at the beginning of the
0068:         *  catch block iff V is DU everywhere in the try block.  Similarly, V
0069:         *  is DU at the beginning of the finally block iff V is DU everywhere
0070:         *  in the try block and in every catch block.  Specifically, the
0071:         *  following bullet is added to 16.2.2
0072:         *  <pre>
0073:         *	V is <em>unassigned everywhere</em> in a block if it is
0074:         *	unassigned before the block and there is no reachable
0075:         *	assignment to V within the block.
0076:         *  </pre>
0077:         *  <p>In 16.2.15, the third bullet (and all of its sub-bullets) for all
0078:         *  try blocks is changed to
0079:         *  <pre>
0080:         *	V is definitely unassigned before a catch block iff V is
0081:         *	definitely unassigned everywhere in the try block.
0082:         *  </pre>
0083:         *  <p>The last bullet (and all of its sub-bullets) for try blocks that
0084:         *  have a finally block is changed to
0085:         *  <pre>
0086:         *	V is definitely unassigned before the finally block iff
0087:         *	V is definitely unassigned everywhere in the try block
0088:         *	and everywhere in each catch block of the try statement.
0089:         *  </pre>
0090:         *  <p>In addition,
0091:         *  <pre>
0092:         *	V is definitely assigned at the end of a constructor iff
0093:         *	V is definitely assigned after the block that is the body
0094:         *	of the constructor and V is definitely assigned at every
0095:         *	return that can return from the constructor.
0096:         *  </pre>
0097:         *  <p>In addition, each continue statement with the loop as its target
0098:         *  is treated as a jump to the end of the loop body, and "intervening"
0099:         *  finally clauses are treated as follows: V is DA "due to the
0100:         *  continue" iff V is DA before the continue statement or V is DA at
0101:         *  the end of any intervening finally block.  V is DU "due to the
0102:         *  continue" iff any intervening finally cannot complete normally or V
0103:         *  is DU at the end of every intervening finally block.  This "due to
0104:         *  the continue" concept is then used in the spec for the loops.
0105:         *
0106:         *  <p>Similarly, break statements must consider intervening finally
0107:         *  blocks.  For liveness analysis, a break statement for which any
0108:         *  intervening finally cannot complete normally is not considered to
0109:         *  cause the target statement to be able to complete normally. Then
0110:         *  we say V is DA "due to the break" iff V is DA before the break or
0111:         *  V is DA at the end of any intervening finally block.  V is DU "due
0112:         *  to the break" iff any intervening finally cannot complete normally
0113:         *  or V is DU at the break and at the end of every intervening
0114:         *  finally block.  (I suspect this latter condition can be
0115:         *  simplified.)  This "due to the break" is then used in the spec for
0116:         *  all statements that can be "broken".
0117:         *
0118:         *  <p>The return statement is treated similarly.  V is DA "due to a
0119:         *  return statement" iff V is DA before the return statement or V is
0120:         *  DA at the end of any intervening finally block.  Note that we
0121:         *  don't have to worry about the return expression because this
0122:         *  concept is only used for construcrors.
0123:         *
0124:         *  <p>There is no spec in JLS2 for when a variable is definitely
0125:         *  assigned at the end of a constructor, which is needed for final
0126:         *  fields (8.3.1.2).  We implement the rule that V is DA at the end
0127:         *  of the constructor iff it is DA and the end of the body of the
0128:         *  constructor and V is DA "due to" every return of the constructor.
0129:         *
0130:         *  <p>Intervening finally blocks similarly affect exception analysis.	An
0131:         *  intervening finally that cannot complete normally allows us to ignore
0132:         *  an otherwise uncaught exception.
0133:         *
0134:         *  <p>To implement the semantics of intervening finally clauses, all
0135:         *  nonlocal transfers (break, continue, return, throw, method call that
0136:         *  can throw a checked exception, and a constructor invocation that can
0137:         *  thrown a checked exception) are recorded in a queue, and removed
0138:         *  from the queue when we complete processing the target of the
0139:         *  nonlocal transfer.  This allows us to modify the queue in accordance
0140:         *  with the above rules when we encounter a finally clause.  The only
0141:         *  exception to this [no pun intended] is that checked exceptions that
0142:         *  are known to be caught or declared to be caught in the enclosing
0143:         *  method are not recorded in the queue, but instead are recorded in a
0144:         *  global variable "Set<Type> thrown" that records the type of all
0145:         *  exceptions that can be thrown.
0146:         *
0147:         *  <p>Other minor issues the treatment of members of other classes
0148:         *  (always considered DA except that within an anonymous class
0149:         *  constructor, where DA status from the enclosing scope is
0150:         *  preserved), treatment of the case expression (V is DA before the
0151:         *  case expression iff V is DA after the switch expression),
0152:         *  treatment of variables declared in a switch block (the implied
0153:         *  DA/DU status after the switch expression is DU and not DA for
0154:         *  variables defined in a switch block), the treatment of boolean ?:
0155:         *  expressions (The JLS rules only handle b and c non-boolean; the
0156:         *  new rule is that if b and c are boolean valued, then V is
0157:         *  (un)assigned after a?b:c when true/false iff V is (un)assigned
0158:         *  after b when true/false and V is (un)assigned after c when
0159:         *  true/false).
0160:         *
0161:         *  <p>There is the remaining question of what syntactic forms constitute a
0162:         *  reference to a variable.  It is conventional to allow this.x on the
0163:         *  left-hand-side to initialize a final instance field named x, yet
0164:         *  this.x isn't considered a "use" when appearing on a right-hand-side
0165:         *  in most implementations.  Should parentheses affect what is
0166:         *  considered a variable reference?  The simplest rule would be to
0167:         *  allow unqualified forms only, parentheses optional, and phase out
0168:         *  support for assigning to a final field via this.x.
0169:         *
0170:         *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
0171:         *  you write code that depends on this, you do so at your own risk.
0172:         *  This code and its internal interfaces are subject to change or
0173:         *  deletion without notice.</b>
0174:         */
0175:        @Version("@(#)Flow.java	1.96 07/06/14")
0176:        public class Flow extends TreeScanner {
0177:            protected static final Context.Key<Flow> flowKey = new Context.Key<Flow>();
0178:
0179:            private final Name.Table names;
0180:            private final Log log;
0181:            private final Symtab syms;
0182:            private final Types types;
0183:            private final Check chk;
0184:            private TreeMaker make;
0185:            private Lint lint;
0186:
0187:            public static Flow instance(Context context) {
0188:                Flow instance = context.get(flowKey);
0189:                if (instance == null)
0190:                    instance = new Flow(context);
0191:                return instance;
0192:            }
0193:
0194:            protected Flow(Context context) {
0195:                context.put(flowKey, this );
0196:
0197:                names = Name.Table.instance(context);
0198:                log = Log.instance(context);
0199:                syms = Symtab.instance(context);
0200:                types = Types.instance(context);
0201:                chk = Check.instance(context);
0202:                lint = Lint.instance(context);
0203:            }
0204:
0205:            /** A flag that indicates whether the last statement could
0206:             *	complete normally.
0207:             */
0208:            private boolean alive;
0209:
0210:            /** The set of definitely assigned variables.
0211:             */
0212:            Bits inits;
0213:
0214:            /** The set of definitely unassigned variables.
0215:             */
0216:            Bits uninits;
0217:
0218:            /** The set of variables that are definitely unassigned everywhere
0219:             *	in current try block. This variable is maintained lazily; it is
0220:             *	updated only when something gets removed from uninits,
0221:             *	typically by being assigned in reachable code.	To obtain the
0222:             *	correct set of variables which are definitely unassigned
0223:             *	anywhere in current try block, intersect uninitsTry and
0224:             *	uninits.
0225:             */
0226:            Bits uninitsTry;
0227:
0228:            /** When analyzing a condition, inits and uninits are null.
0229:             *	Instead we have:
0230:             */
0231:            Bits initsWhenTrue;
0232:            Bits initsWhenFalse;
0233:            Bits uninitsWhenTrue;
0234:            Bits uninitsWhenFalse;
0235:
0236:            /** A mapping from addresses to variable symbols.
0237:             */
0238:            VarSymbol[] vars;
0239:
0240:            /** The current class being defined.
0241:             */
0242:            JCClassDecl classDef;
0243:
0244:            /** The first variable sequence number in this class definition.
0245:             */
0246:            int firstadr;
0247:
0248:            /** The next available variable sequence number.
0249:             */
0250:            int nextadr;
0251:
0252:            /** The list of possibly thrown declarable exceptions.
0253:             */
0254:            List<Type> thrown;
0255:
0256:            /** The list of exceptions that are either caught or declared to be
0257:             *	thrown.
0258:             */
0259:            List<Type> caught;
0260:
0261:            /** Set when processing a loop body the second time for DU analysis. */
0262:            boolean loopPassTwo = false;
0263:
0264:            /*-------------------- Environments ----------------------*/
0265:
0266:            /** A pending exit.	 These are the statements return, break, and
0267:             *	continue.  In addition, exception-throwing expressions or
0268:             *	statements are put here when not known to be caught.  This
0269:             *	will typically result in an error unless it is within a
0270:             *	try-finally whose finally block cannot complete normally.
0271:             */
0272:            static class PendingExit {
0273:                JCTree tree;
0274:                Bits inits;
0275:                Bits uninits;
0276:                Type thrown;
0277:
0278:                PendingExit(JCTree tree, Bits inits, Bits uninits) {
0279:                    this .tree = tree;
0280:                    this .inits = inits.dup();
0281:                    this .uninits = uninits.dup();
0282:                }
0283:
0284:                PendingExit(JCTree tree, Type thrown) {
0285:                    this .tree = tree;
0286:                    this .thrown = thrown;
0287:                }
0288:            }
0289:
0290:            /** The currently pending exits that go from current inner blocks
0291:             *	to an enclosing block, in source order.
0292:             */
0293:            ListBuffer<PendingExit> pendingExits;
0294:
0295:            /*-------------------- Exceptions ----------------------*/
0296:
0297:            /** Complain that pending exceptions are not caught.
0298:             */
0299:            void errorUncaught() {
0300:                for (PendingExit exit = pendingExits.next(); exit != null; exit = pendingExits
0301:                        .next()) {
0302:                    boolean synthetic = classDef != null
0303:                            && classDef.pos == exit.tree.pos;
0304:                    log
0305:                            .error(
0306:                                    exit.tree.pos(),
0307:                                    synthetic ? "unreported.exception.default.constructor"
0308:                                            : "unreported.exception.need.to.catch.or.throw",
0309:                                    exit.thrown);
0310:                }
0311:            }
0312:
0313:            /** Record that exception is potentially thrown and check that it
0314:             *	is caught.
0315:             */
0316:            void markThrown(JCTree tree, Type exc) {
0317:                if (!chk.isUnchecked(tree.pos(), exc)) {
0318:                    if (!chk.isHandled(exc, caught))
0319:                        pendingExits.append(new PendingExit(tree, exc));
0320:                    thrown = chk.incl(exc, thrown);
0321:                }
0322:            }
0323:
0324:            /*-------------- Processing variables ----------------------*/
0325:
0326:            /** Do we need to track init/uninit state of this symbol?
0327:             *	I.e. is symbol either a local or a blank final variable?
0328:             */
0329:            boolean trackable(VarSymbol sym) {
0330:                return (sym.owner.kind == MTH || ((sym.flags() & (FINAL
0331:                        | HASINIT | PARAMETER)) == FINAL && classDef.sym
0332:                        .isEnclosedBy((ClassSymbol) sym.owner)));
0333:            }
0334:
0335:            /** Initialize new trackable variable by setting its address field
0336:             *	to the next available sequence number and entering it under that
0337:             *	index into the vars array.
0338:             */
0339:            void newVar(VarSymbol sym) {
0340:                if (nextadr == vars.length) {
0341:                    VarSymbol[] newvars = new VarSymbol[nextadr * 2];
0342:                    System.arraycopy(vars, 0, newvars, 0, nextadr);
0343:                    vars = newvars;
0344:                }
0345:                sym.adr = nextadr;
0346:                vars[nextadr] = sym;
0347:                inits.excl(nextadr);
0348:                uninits.incl(nextadr);
0349:                nextadr++;
0350:            }
0351:
0352:            /** Record an initialization of a trackable variable.
0353:             */
0354:            void letInit(DiagnosticPosition pos, VarSymbol sym) {
0355:                if (sym.adr >= firstadr && trackable(sym)) {
0356:                    if ((sym.flags() & FINAL) != 0) {
0357:                        if ((sym.flags() & PARAMETER) != 0) {
0358:                            log.error(pos,
0359:                                    "final.parameter.may.not.be.assigned", sym);
0360:                        } else if (!uninits.isMember(sym.adr)) {
0361:                            log
0362:                                    .error(
0363:                                            pos,
0364:                                            loopPassTwo ? "var.might.be.assigned.in.loop"
0365:                                                    : "var.might.already.be.assigned",
0366:                                            sym);
0367:                        } else if (!inits.isMember(sym.adr)) {
0368:                            // reachable assignment
0369:                            uninits.excl(sym.adr);
0370:                            uninitsTry.excl(sym.adr);
0371:                        } else {
0372:                            //log.rawWarning(pos, "unreachable assignment");//DEBUG
0373:                            uninits.excl(sym.adr);
0374:                        }
0375:                    }
0376:                    inits.incl(sym.adr);
0377:                } else if ((sym.flags() & FINAL) != 0) {
0378:                    log.error(pos, "var.might.already.be.assigned", sym);
0379:                }
0380:            }
0381:
0382:            /** If tree is either a simple name or of the form this.name or
0383:             *	C.this.name, and tree represents a trackable variable,
0384:             *	record an initialization of the variable.
0385:             */
0386:            void letInit(JCTree tree) {
0387:                tree = TreeInfo.skipParens(tree);
0388:                if (tree.getTag() == JCTree.IDENT
0389:                        || tree.getTag() == JCTree.SELECT) {
0390:                    Symbol sym = TreeInfo.symbol(tree);
0391:                    letInit(tree.pos(), (VarSymbol) sym);
0392:                }
0393:            }
0394:
0395:            /** Check that trackable variable is initialized.
0396:             */
0397:            void checkInit(DiagnosticPosition pos, VarSymbol sym) {
0398:                if ((sym.adr >= firstadr || sym.owner.kind != TYP)
0399:                        && trackable(sym) && !inits.isMember(sym.adr)) {
0400:                    log.error(pos, "var.might.not.have.been.initialized", sym);
0401:                    inits.incl(sym.adr);
0402:                }
0403:            }
0404:
0405:            /*-------------------- Handling jumps ----------------------*/
0406:
0407:            /** Record an outward transfer of control. */
0408:            void recordExit(JCTree tree) {
0409:                pendingExits.append(new PendingExit(tree, inits, uninits));
0410:                markDead();
0411:            }
0412:
0413:            /** Resolve all breaks of this statement. */
0414:            boolean resolveBreaks(JCTree tree,
0415:                    ListBuffer<PendingExit> oldPendingExits) {
0416:                boolean result = false;
0417:                List<PendingExit> exits = pendingExits.toList();
0418:                pendingExits = oldPendingExits;
0419:                for (; exits.nonEmpty(); exits = exits.tail) {
0420:                    PendingExit exit = exits.head;
0421:                    if (exit.tree.getTag() == JCTree.BREAK
0422:                            && ((JCBreak) exit.tree).target == tree) {
0423:                        inits.andSet(exit.inits);
0424:                        uninits.andSet(exit.uninits);
0425:                        result = true;
0426:                    } else {
0427:                        pendingExits.append(exit);
0428:                    }
0429:                }
0430:                return result;
0431:            }
0432:
0433:            /** Resolve all continues of this statement. */
0434:            boolean resolveContinues(JCTree tree) {
0435:                boolean result = false;
0436:                List<PendingExit> exits = pendingExits.toList();
0437:                pendingExits = new ListBuffer<PendingExit>();
0438:                for (; exits.nonEmpty(); exits = exits.tail) {
0439:                    PendingExit exit = exits.head;
0440:                    if (exit.tree.getTag() == JCTree.CONTINUE
0441:                            && ((JCContinue) exit.tree).target == tree) {
0442:                        inits.andSet(exit.inits);
0443:                        uninits.andSet(exit.uninits);
0444:                        result = true;
0445:                    } else {
0446:                        pendingExits.append(exit);
0447:                    }
0448:                }
0449:                return result;
0450:            }
0451:
0452:            /** Record that statement is unreachable.
0453:             */
0454:            void markDead() {
0455:                inits.inclRange(firstadr, nextadr);
0456:                uninits.inclRange(firstadr, nextadr);
0457:                alive = false;
0458:            }
0459:
0460:            /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
0461:             */
0462:            void split() {
0463:                initsWhenFalse = inits.dup();
0464:                uninitsWhenFalse = uninits.dup();
0465:                initsWhenTrue = inits;
0466:                uninitsWhenTrue = uninits;
0467:                inits = uninits = null;
0468:            }
0469:
0470:            /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
0471:             */
0472:            void merge() {
0473:                inits = initsWhenFalse.andSet(initsWhenTrue);
0474:                uninits = uninitsWhenFalse.andSet(uninitsWhenTrue);
0475:            }
0476:
0477:            /* ************************************************************************
0478:             * Visitor methods for statements and definitions
0479:             *************************************************************************/
0480:
0481:            /** Analyze a definition.
0482:             */
0483:            void scanDef(JCTree tree) {
0484:                scanStat(tree);
0485:                if (tree != null && tree.getTag() == JCTree.BLOCK && !alive) {
0486:                    log.error(tree.pos(),
0487:                            "initializer.must.be.able.to.complete.normally");
0488:                }
0489:            }
0490:
0491:            /** Analyze a statement. Check that statement is reachable.
0492:             */
0493:            void scanStat(JCTree tree) {
0494:                if (!alive && tree != null) {
0495:                    log.error(tree.pos(), "unreachable.stmt");
0496:                    if (tree.getTag() != JCTree.SKIP)
0497:                        alive = true;
0498:                }
0499:                scan(tree);
0500:            }
0501:
0502:            /** Analyze list of statements.
0503:             */
0504:            void scanStats(List<? extends JCStatement> trees) {
0505:                if (trees != null)
0506:                    for (List<? extends JCStatement> l = trees; l.nonEmpty(); l = l.tail)
0507:                        scanStat(l.head);
0508:            }
0509:
0510:            /** Analyze an expression. Make sure to set (un)inits rather than
0511:             *	(un)initsWhenTrue(WhenFalse) on exit.
0512:             */
0513:            void scanExpr(JCTree tree) {
0514:                if (tree != null) {
0515:                    scan(tree);
0516:                    if (inits == null)
0517:                        merge();
0518:                }
0519:            }
0520:
0521:            /** Analyze a list of expressions.
0522:             */
0523:            void scanExprs(List<? extends JCExpression> trees) {
0524:                if (trees != null)
0525:                    for (List<? extends JCExpression> l = trees; l.nonEmpty(); l = l.tail)
0526:                        scanExpr(l.head);
0527:            }
0528:
0529:            /** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
0530:             *	rather than (un)inits on exit.
0531:             */
0532:            void scanCond(JCTree tree) {
0533:                if (tree.type.isFalse()) {
0534:                    if (inits == null)
0535:                        merge();
0536:                    initsWhenTrue = inits.dup();
0537:                    initsWhenTrue.inclRange(firstadr, nextadr);
0538:                    uninitsWhenTrue = uninits.dup();
0539:                    uninitsWhenTrue.inclRange(firstadr, nextadr);
0540:                    initsWhenFalse = inits;
0541:                    uninitsWhenFalse = uninits;
0542:                } else if (tree.type.isTrue()) {
0543:                    if (inits == null)
0544:                        merge();
0545:                    initsWhenFalse = inits.dup();
0546:                    initsWhenFalse.inclRange(firstadr, nextadr);
0547:                    uninitsWhenFalse = uninits.dup();
0548:                    uninitsWhenFalse.inclRange(firstadr, nextadr);
0549:                    initsWhenTrue = inits;
0550:                    uninitsWhenTrue = uninits;
0551:                } else {
0552:                    scan(tree);
0553:                    if (inits != null)
0554:                        split();
0555:                }
0556:                inits = uninits = null;
0557:            }
0558:
0559:            /* ------------ Visitor methods for various sorts of trees -------------*/
0560:
0561:            public void visitClassDef(JCClassDecl tree) {
0562:                if (tree.sym == null)
0563:                    return;
0564:
0565:                JCClassDecl classDefPrev = classDef;
0566:                List<Type> thrownPrev = thrown;
0567:                List<Type> caughtPrev = caught;
0568:                boolean alivePrev = alive;
0569:                int firstadrPrev = firstadr;
0570:                int nextadrPrev = nextadr;
0571:                ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
0572:                Lint lintPrev = lint;
0573:
0574:                pendingExits = new ListBuffer<PendingExit>();
0575:                if (tree.name != names.empty) {
0576:                    caught = List.nil();
0577:                    firstadr = nextadr;
0578:                }
0579:                classDef = tree;
0580:                thrown = List.nil();
0581:                lint = lint.augment(tree.sym.attributes_field);
0582:
0583:                try {
0584:                    // define all the static fields
0585:                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0586:                        if (l.head.getTag() == JCTree.VARDEF) {
0587:                            JCVariableDecl def = (JCVariableDecl) l.head;
0588:                            if ((def.mods.flags & STATIC) != 0) {
0589:                                VarSymbol sym = def.sym;
0590:                                if (trackable(sym))
0591:                                    newVar(sym);
0592:                            }
0593:                        }
0594:                    }
0595:
0596:                    // process all the static initializers
0597:                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0598:                        if (l.head.getTag() != JCTree.METHODDEF
0599:                                && (TreeInfo.flags(l.head) & STATIC) != 0) {
0600:                            scanDef(l.head);
0601:                            errorUncaught();
0602:                        }
0603:                    }
0604:
0605:                    // add intersection of all thrown clauses of initial constructors
0606:                    // to set of caught exceptions, unless class is anonymous.
0607:                    if (tree.name != names.empty) {
0608:                        boolean firstConstructor = true;
0609:                        for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0610:                            if (TreeInfo.isInitialConstructor(l.head)) {
0611:                                List<Type> mthrown = ((JCMethodDecl) l.head).sym.type
0612:                                        .getThrownTypes();
0613:                                if (firstConstructor) {
0614:                                    caught = mthrown;
0615:                                    firstConstructor = false;
0616:                                } else {
0617:                                    caught = chk.intersect(mthrown, caught);
0618:                                }
0619:                            }
0620:                        }
0621:                    }
0622:
0623:                    // define all the instance fields
0624:                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0625:                        if (l.head.getTag() == JCTree.VARDEF) {
0626:                            JCVariableDecl def = (JCVariableDecl) l.head;
0627:                            if ((def.mods.flags & STATIC) == 0) {
0628:                                VarSymbol sym = def.sym;
0629:                                if (trackable(sym))
0630:                                    newVar(sym);
0631:                            }
0632:                        }
0633:                    }
0634:
0635:                    // process all the instance initializers
0636:                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0637:                        if (l.head.getTag() != JCTree.METHODDEF
0638:                                && (TreeInfo.flags(l.head) & STATIC) == 0) {
0639:                            scanDef(l.head);
0640:                            errorUncaught();
0641:                        }
0642:                    }
0643:
0644:                    // in an anonymous class, add the set of thrown exceptions to
0645:                    // the throws clause of the synthetic constructor and propagate
0646:                    // outwards.
0647:                    if (tree.name == names.empty) {
0648:                        for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0649:                            if (TreeInfo.isInitialConstructor(l.head)) {
0650:                                JCMethodDecl mdef = (JCMethodDecl) l.head;
0651:                                mdef.thrown = make.Types(thrown);
0652:                                mdef.sym.type.setThrown(thrown);
0653:                            }
0654:                        }
0655:                        thrownPrev = chk.union(thrown, thrownPrev);
0656:                    }
0657:
0658:                    // process all the methods
0659:                    for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0660:                        if (l.head.getTag() == JCTree.METHODDEF) {
0661:                            scan(l.head);
0662:                            errorUncaught();
0663:                        }
0664:                    }
0665:
0666:                    thrown = thrownPrev;
0667:                } finally {
0668:                    pendingExits = pendingExitsPrev;
0669:                    alive = alivePrev;
0670:                    nextadr = nextadrPrev;
0671:                    firstadr = firstadrPrev;
0672:                    caught = caughtPrev;
0673:                    classDef = classDefPrev;
0674:                    lint = lintPrev;
0675:                }
0676:            }
0677:
0678:            public void visitMethodDef(JCMethodDecl tree) {
0679:                if (tree.body == null)
0680:                    return;
0681:
0682:                List<Type> caughtPrev = caught;
0683:                List<Type> mthrown = tree.sym.type.getThrownTypes();
0684:                Bits initsPrev = inits.dup();
0685:                Bits uninitsPrev = uninits.dup();
0686:                int nextadrPrev = nextadr;
0687:                int firstadrPrev = firstadr;
0688:                Lint lintPrev = lint;
0689:
0690:                lint = lint.augment(tree.sym.attributes_field);
0691:
0692:                assert pendingExits.isEmpty();
0693:
0694:                try {
0695:                    boolean isInitialConstructor = TreeInfo
0696:                            .isInitialConstructor(tree);
0697:
0698:                    if (!isInitialConstructor)
0699:                        firstadr = nextadr;
0700:                    for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
0701:                        JCVariableDecl def = l.head;
0702:                        scan(def);
0703:                        inits.incl(def.sym.adr);
0704:                        uninits.excl(def.sym.adr);
0705:                    }
0706:                    if (isInitialConstructor)
0707:                        caught = chk.union(caught, mthrown);
0708:                    else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
0709:                        caught = mthrown;
0710:                    // else we are in an instance initializer block;
0711:                    // leave caught unchanged.
0712:
0713:                    alive = true;
0714:                    scanStat(tree.body);
0715:
0716:                    if (alive && tree.sym.type.getReturnType().tag != VOID)
0717:                        log.error(TreeInfo.diagEndPos(tree.body),
0718:                                "missing.ret.stmt");
0719:
0720:                    if (isInitialConstructor) {
0721:                        for (int i = firstadr; i < nextadr; i++)
0722:                            if (vars[i].owner == classDef.sym)
0723:                                checkInit(TreeInfo.diagEndPos(tree.body),
0724:                                        vars[i]);
0725:                    }
0726:                    List<PendingExit> exits = pendingExits.toList();
0727:                    pendingExits = new ListBuffer<PendingExit>();
0728:                    while (exits.nonEmpty()) {
0729:                        PendingExit exit = exits.head;
0730:                        exits = exits.tail;
0731:                        if (exit.thrown == null) {
0732:                            assert exit.tree.getTag() == JCTree.RETURN;
0733:                            if (isInitialConstructor) {
0734:                                inits = exit.inits;
0735:                                for (int i = firstadr; i < nextadr; i++)
0736:                                    checkInit(exit.tree.pos(), vars[i]);
0737:                            }
0738:                        } else {
0739:                            // uncaught throws will be reported later
0740:                            pendingExits.append(exit);
0741:                        }
0742:                    }
0743:                } finally {
0744:                    inits = initsPrev;
0745:                    uninits = uninitsPrev;
0746:                    nextadr = nextadrPrev;
0747:                    firstadr = firstadrPrev;
0748:                    caught = caughtPrev;
0749:                    lint = lintPrev;
0750:                }
0751:            }
0752:
0753:            public void visitVarDef(JCVariableDecl tree) {
0754:                boolean track = trackable(tree.sym);
0755:                if (track && tree.sym.owner.kind == MTH)
0756:                    newVar(tree.sym);
0757:                if (tree.init != null) {
0758:                    Lint lintPrev = lint;
0759:                    lint = lint.augment(tree.sym.attributes_field);
0760:                    try {
0761:                        scanExpr(tree.init);
0762:                        if (track)
0763:                            letInit(tree.pos(), tree.sym);
0764:                    } finally {
0765:                        lint = lintPrev;
0766:                    }
0767:                }
0768:            }
0769:
0770:            public void visitBlock(JCBlock tree) {
0771:                int nextadrPrev = nextadr;
0772:                scanStats(tree.stats);
0773:                nextadr = nextadrPrev;
0774:            }
0775:
0776:            public void visitDoLoop(JCDoWhileLoop tree) {
0777:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0778:                boolean prevLoopPassTwo = loopPassTwo;
0779:                pendingExits = new ListBuffer<PendingExit>();
0780:                do {
0781:                    Bits uninitsEntry = uninits.dup();
0782:                    scanStat(tree.body);
0783:                    alive |= resolveContinues(tree);
0784:                    scanCond(tree.cond);
0785:                    if (log.nerrors != 0
0786:                            || loopPassTwo
0787:                            || uninitsEntry.diffSet(uninitsWhenTrue).nextBit(
0788:                                    firstadr) == -1)
0789:                        break;
0790:                    inits = initsWhenTrue;
0791:                    uninits = uninitsEntry.andSet(uninitsWhenTrue);
0792:                    loopPassTwo = true;
0793:                    alive = true;
0794:                } while (true);
0795:                loopPassTwo = prevLoopPassTwo;
0796:                inits = initsWhenFalse;
0797:                uninits = uninitsWhenFalse;
0798:                alive = alive && !tree.cond.type.isTrue();
0799:                alive |= resolveBreaks(tree, prevPendingExits);
0800:            }
0801:
0802:            public void visitWhileLoop(JCWhileLoop tree) {
0803:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0804:                boolean prevLoopPassTwo = loopPassTwo;
0805:                Bits initsCond;
0806:                Bits uninitsCond;
0807:                pendingExits = new ListBuffer<PendingExit>();
0808:                do {
0809:                    Bits uninitsEntry = uninits.dup();
0810:                    scanCond(tree.cond);
0811:                    initsCond = initsWhenFalse;
0812:                    uninitsCond = uninitsWhenFalse;
0813:                    inits = initsWhenTrue;
0814:                    uninits = uninitsWhenTrue;
0815:                    alive = !tree.cond.type.isFalse();
0816:                    scanStat(tree.body);
0817:                    alive |= resolveContinues(tree);
0818:                    if (log.nerrors != 0
0819:                            || loopPassTwo
0820:                            || uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1)
0821:                        break;
0822:                    uninits = uninitsEntry.andSet(uninits);
0823:                    loopPassTwo = true;
0824:                    alive = true;
0825:                } while (true);
0826:                loopPassTwo = prevLoopPassTwo;
0827:                inits = initsCond;
0828:                uninits = uninitsCond;
0829:                alive = resolveBreaks(tree, prevPendingExits)
0830:                        || !tree.cond.type.isTrue();
0831:            }
0832:
0833:            public void visitForLoop(JCForLoop tree) {
0834:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0835:                boolean prevLoopPassTwo = loopPassTwo;
0836:                int nextadrPrev = nextadr;
0837:                scanStats(tree.init);
0838:                Bits initsCond;
0839:                Bits uninitsCond;
0840:                pendingExits = new ListBuffer<PendingExit>();
0841:                do {
0842:                    Bits uninitsEntry = uninits.dup();
0843:                    if (tree.cond != null) {
0844:                        scanCond(tree.cond);
0845:                        initsCond = initsWhenFalse;
0846:                        uninitsCond = uninitsWhenFalse;
0847:                        inits = initsWhenTrue;
0848:                        uninits = uninitsWhenTrue;
0849:                        alive = !tree.cond.type.isFalse();
0850:                    } else {
0851:                        initsCond = inits.dup();
0852:                        initsCond.inclRange(firstadr, nextadr);
0853:                        uninitsCond = uninits.dup();
0854:                        uninitsCond.inclRange(firstadr, nextadr);
0855:                        alive = true;
0856:                    }
0857:                    scanStat(tree.body);
0858:                    alive |= resolveContinues(tree);
0859:                    scan(tree.step);
0860:                    if (log.nerrors != 0
0861:                            || loopPassTwo
0862:                            || uninitsEntry.dup().diffSet(uninits).nextBit(
0863:                                    firstadr) == -1)
0864:                        break;
0865:                    uninits = uninitsEntry.andSet(uninits);
0866:                    loopPassTwo = true;
0867:                    alive = true;
0868:                } while (true);
0869:                loopPassTwo = prevLoopPassTwo;
0870:                inits = initsCond;
0871:                uninits = uninitsCond;
0872:                alive = resolveBreaks(tree, prevPendingExits)
0873:                        || tree.cond != null && !tree.cond.type.isTrue();
0874:                nextadr = nextadrPrev;
0875:            }
0876:
0877:            public void visitForeachLoop(JCEnhancedForLoop tree) {
0878:                visitVarDef(tree.var);
0879:
0880:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0881:                boolean prevLoopPassTwo = loopPassTwo;
0882:                int nextadrPrev = nextadr;
0883:                scan(tree.expr);
0884:                Bits initsStart = inits.dup();
0885:                Bits uninitsStart = uninits.dup();
0886:
0887:                letInit(tree.pos(), tree.var.sym);
0888:                pendingExits = new ListBuffer<PendingExit>();
0889:                do {
0890:                    Bits uninitsEntry = uninits.dup();
0891:                    scanStat(tree.body);
0892:                    alive |= resolveContinues(tree);
0893:                    if (log.nerrors != 0
0894:                            || loopPassTwo
0895:                            || uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1)
0896:                        break;
0897:                    uninits = uninitsEntry.andSet(uninits);
0898:                    loopPassTwo = true;
0899:                    alive = true;
0900:                } while (true);
0901:                loopPassTwo = prevLoopPassTwo;
0902:                inits = initsStart;
0903:                uninits = uninitsStart.andSet(uninits);
0904:                resolveBreaks(tree, prevPendingExits);
0905:                alive = true;
0906:                nextadr = nextadrPrev;
0907:            }
0908:
0909:            public void visitLabelled(JCLabeledStatement tree) {
0910:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0911:                pendingExits = new ListBuffer<PendingExit>();
0912:                scanStat(tree.body);
0913:                alive |= resolveBreaks(tree, prevPendingExits);
0914:            }
0915:
0916:            public void visitSwitch(JCSwitch tree) {
0917:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0918:                pendingExits = new ListBuffer<PendingExit>();
0919:                int nextadrPrev = nextadr;
0920:                scanExpr(tree.selector);
0921:                Bits initsSwitch = inits;
0922:                Bits uninitsSwitch = uninits.dup();
0923:                boolean hasDefault = false;
0924:                for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
0925:                    alive = true;
0926:                    inits = initsSwitch.dup();
0927:                    uninits = uninits.andSet(uninitsSwitch);
0928:                    JCCase c = l.head;
0929:                    if (c.pat == null)
0930:                        hasDefault = true;
0931:                    else
0932:                        scanExpr(c.pat);
0933:                    scanStats(c.stats);
0934:                    addVars(c.stats, initsSwitch, uninitsSwitch);
0935:                    // Warn about fall-through if lint switch fallthrough enabled.
0936:                    if (!loopPassTwo && alive
0937:                            && lint.isEnabled(Lint.LintCategory.FALLTHROUGH)
0938:                            && c.stats.nonEmpty() && l.tail.nonEmpty())
0939:                        log.warning(l.tail.head.pos(),
0940:                                "possible.fall-through.into.case");
0941:                }
0942:                if (!hasDefault) {
0943:                    inits.andSet(initsSwitch);
0944:                    alive = true;
0945:                }
0946:                alive |= resolveBreaks(tree, prevPendingExits);
0947:                nextadr = nextadrPrev;
0948:            }
0949:
0950:            // where
0951:            /** Add any variables defined in stats to inits and uninits. */
0952:            private static void addVars(List<JCStatement> stats, Bits inits,
0953:                    Bits uninits) {
0954:                for (; stats.nonEmpty(); stats = stats.tail) {
0955:                    JCTree stat = stats.head;
0956:                    if (stat.getTag() == JCTree.VARDEF) {
0957:                        int adr = ((JCVariableDecl) stat).sym.adr;
0958:                        inits.excl(adr);
0959:                        uninits.incl(adr);
0960:                    }
0961:                }
0962:            }
0963:
0964:            public void visitTry(JCTry tree) {
0965:                List<Type> caughtPrev = caught;
0966:                List<Type> thrownPrev = thrown;
0967:                thrown = List.nil();
0968:                for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail)
0969:                    caught = chk.incl(l.head.param.type, caught);
0970:                Bits uninitsTryPrev = uninitsTry;
0971:                ListBuffer<PendingExit> prevPendingExits = pendingExits;
0972:                pendingExits = new ListBuffer<PendingExit>();
0973:                Bits initsTry = inits.dup();
0974:                uninitsTry = uninits.dup();
0975:                scanStat(tree.body);
0976:                List<Type> thrownInTry = thrown;
0977:                thrown = thrownPrev;
0978:                caught = caughtPrev;
0979:                boolean aliveEnd = alive;
0980:                uninitsTry.andSet(uninits);
0981:                Bits initsEnd = inits;
0982:                Bits uninitsEnd = uninits;
0983:                int nextadrCatch = nextadr;
0984:
0985:                List<Type> caughtInTry = List.nil();
0986:                for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
0987:                    alive = true;
0988:                    JCVariableDecl param = l.head.param;
0989:                    Type exc = param.type;
0990:                    if (chk.subset(exc, caughtInTry)) {
0991:                        log.error(l.head.pos(), "except.already.caught", exc);
0992:                    } else if (!chk.isUnchecked(l.head.pos(), exc)
0993:                            && exc.tsym != syms.throwableType.tsym
0994:                            && exc.tsym != syms.exceptionType.tsym
0995:                            && !chk.intersects(exc, thrownInTry)) {
0996:                        log.error(l.head.pos(), "except.never.thrown.in.try",
0997:                                exc);
0998:                    }
0999:                    caughtInTry = chk.incl(exc, caughtInTry);
1000:                    inits = initsTry.dup();
1001:                    uninits = uninitsTry.dup();
1002:                    scan(param);
1003:                    inits.incl(param.sym.adr);
1004:                    uninits.excl(param.sym.adr);
1005:                    scanStat(l.head.body);
1006:                    initsEnd.andSet(inits);
1007:                    uninitsEnd.andSet(uninits);
1008:                    nextadr = nextadrCatch;
1009:                    aliveEnd |= alive;
1010:                }
1011:                if (tree.finalizer != null) {
1012:                    List<Type> savedThrown = thrown;
1013:                    thrown = List.nil();
1014:                    inits = initsTry.dup();
1015:                    uninits = uninitsTry.dup();
1016:                    ListBuffer<PendingExit> exits = pendingExits;
1017:                    pendingExits = prevPendingExits;
1018:                    alive = true;
1019:                    scanStat(tree.finalizer);
1020:                    if (!alive) {
1021:                        // discard exits and exceptions from try and finally
1022:                        thrown = chk.union(thrown, thrownPrev);
1023:                        if (!loopPassTwo
1024:                                && lint.isEnabled(Lint.LintCategory.FINALLY)) {
1025:                            log.warning(TreeInfo.diagEndPos(tree.finalizer),
1026:                                    "finally.cannot.complete");
1027:                        }
1028:                    } else {
1029:                        thrown = chk.union(thrown, chk.diff(thrownInTry,
1030:                                caughtInTry));
1031:                        thrown = chk.union(thrown, savedThrown);
1032:                        uninits.andSet(uninitsEnd);
1033:                        // FIX: this doesn't preserve source order of exits in catch
1034:                        // versus finally!
1035:                        while (exits.nonEmpty()) {
1036:                            PendingExit exit = exits.next();
1037:                            if (exit.inits != null) {
1038:                                exit.inits.orSet(inits);
1039:                                exit.uninits.andSet(uninits);
1040:                            }
1041:                            pendingExits.append(exit);
1042:                        }
1043:                        inits.orSet(initsEnd);
1044:                        alive = aliveEnd;
1045:                    }
1046:                } else {
1047:                    thrown = chk.union(thrown, chk.diff(thrownInTry,
1048:                            caughtInTry));
1049:                    inits = initsEnd;
1050:                    uninits = uninitsEnd;
1051:                    alive = aliveEnd;
1052:                    ListBuffer<PendingExit> exits = pendingExits;
1053:                    pendingExits = prevPendingExits;
1054:                    while (exits.nonEmpty())
1055:                        pendingExits.append(exits.next());
1056:                }
1057:                uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
1058:            }
1059:
1060:            public void visitConditional(JCConditional tree) {
1061:                scanCond(tree.cond);
1062:                Bits initsBeforeElse = initsWhenFalse;
1063:                Bits uninitsBeforeElse = uninitsWhenFalse;
1064:                inits = initsWhenTrue;
1065:                uninits = uninitsWhenTrue;
1066:                if (tree.truepart.type.tag == BOOLEAN
1067:                        && tree.falsepart.type.tag == BOOLEAN) {
1068:                    // if b and c are boolean valued, then
1069:                    // v is (un)assigned after a?b:c when true iff
1070:                    //    v is (un)assigned after b when true and
1071:                    //    v is (un)assigned after c when true
1072:                    scanCond(tree.truepart);
1073:                    Bits initsAfterThenWhenTrue = initsWhenTrue.dup();
1074:                    Bits initsAfterThenWhenFalse = initsWhenFalse.dup();
1075:                    Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup();
1076:                    Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup();
1077:                    inits = initsBeforeElse;
1078:                    uninits = uninitsBeforeElse;
1079:                    scanCond(tree.falsepart);
1080:                    initsWhenTrue.andSet(initsAfterThenWhenTrue);
1081:                    initsWhenFalse.andSet(initsAfterThenWhenFalse);
1082:                    uninitsWhenTrue.andSet(uninitsAfterThenWhenTrue);
1083:                    uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse);
1084:                } else {
1085:                    scanExpr(tree.truepart);
1086:                    Bits initsAfterThen = inits.dup();
1087:                    Bits uninitsAfterThen = uninits.dup();
1088:                    inits = initsBeforeElse;
1089:                    uninits = uninitsBeforeElse;
1090:                    scanExpr(tree.falsepart);
1091:                    inits.andSet(initsAfterThen);
1092:                    uninits.andSet(uninitsAfterThen);
1093:                }
1094:            }
1095:
1096:            public void visitIf(JCIf tree) {
1097:                scanCond(tree.cond);
1098:                Bits initsBeforeElse = initsWhenFalse;
1099:                Bits uninitsBeforeElse = uninitsWhenFalse;
1100:                inits = initsWhenTrue;
1101:                uninits = uninitsWhenTrue;
1102:                scanStat(tree.thenpart);
1103:                if (tree.elsepart != null) {
1104:                    boolean aliveAfterThen = alive;
1105:                    alive = true;
1106:                    Bits initsAfterThen = inits.dup();
1107:                    Bits uninitsAfterThen = uninits.dup();
1108:                    inits = initsBeforeElse;
1109:                    uninits = uninitsBeforeElse;
1110:                    scanStat(tree.elsepart);
1111:                    inits.andSet(initsAfterThen);
1112:                    uninits.andSet(uninitsAfterThen);
1113:                    alive = alive | aliveAfterThen;
1114:                } else {
1115:                    inits.andSet(initsBeforeElse);
1116:                    uninits.andSet(uninitsBeforeElse);
1117:                    alive = true;
1118:                }
1119:            }
1120:
1121:            public void visitBreak(JCBreak tree) {
1122:                recordExit(tree);
1123:            }
1124:
1125:            public void visitContinue(JCContinue tree) {
1126:                recordExit(tree);
1127:            }
1128:
1129:            public void visitReturn(JCReturn tree) {
1130:                scanExpr(tree.expr);
1131:                // if not initial constructor, should markDead instead of recordExit
1132:                recordExit(tree);
1133:            }
1134:
1135:            public void visitThrow(JCThrow tree) {
1136:                scanExpr(tree.expr);
1137:                markThrown(tree, tree.expr.type);
1138:                markDead();
1139:            }
1140:
1141:            public void visitApply(JCMethodInvocation tree) {
1142:                scanExpr(tree.meth);
1143:                scanExprs(tree.args);
1144:                for (List<Type> l = tree.meth.type.getThrownTypes(); l
1145:                        .nonEmpty(); l = l.tail)
1146:                    markThrown(tree, l.head);
1147:            }
1148:
1149:            public void visitNewClass(JCNewClass tree) {
1150:                scanExpr(tree.encl);
1151:                scanExprs(tree.args);
1152:                // scan(tree.def);
1153:                for (List<Type> l = tree.constructor.type.getThrownTypes(); l
1154:                        .nonEmpty(); l = l.tail)
1155:                    markThrown(tree, l.head);
1156:                scan(tree.def);
1157:            }
1158:
1159:            public void visitNewArray(JCNewArray tree) {
1160:                scanExprs(tree.dims);
1161:                scanExprs(tree.elems);
1162:            }
1163:
1164:            public void visitAssert(JCAssert tree) {
1165:                Bits initsExit = inits.dup();
1166:                Bits uninitsExit = uninits.dup();
1167:                scanCond(tree.cond);
1168:                uninitsExit.andSet(uninitsWhenTrue);
1169:                if (tree.detail != null) {
1170:                    inits = initsWhenFalse;
1171:                    uninits = uninitsWhenFalse;
1172:                    scanExpr(tree.detail);
1173:                }
1174:                inits = initsExit;
1175:                uninits = uninitsExit;
1176:            }
1177:
1178:            public void visitAssign(JCAssign tree) {
1179:                JCTree lhs = TreeInfo.skipParens(tree.lhs);
1180:                if (!(lhs instanceof  JCIdent))
1181:                    scanExpr(lhs);
1182:                scanExpr(tree.rhs);
1183:                letInit(lhs);
1184:            }
1185:
1186:            public void visitAssignop(JCAssignOp tree) {
1187:                scanExpr(tree.lhs);
1188:                scanExpr(tree.rhs);
1189:                letInit(tree.lhs);
1190:            }
1191:
1192:            public void visitUnary(JCUnary tree) {
1193:                switch (tree.getTag()) {
1194:                case JCTree.NOT:
1195:                    scanCond(tree.arg);
1196:                    Bits t = initsWhenFalse;
1197:                    initsWhenFalse = initsWhenTrue;
1198:                    initsWhenTrue = t;
1199:                    t = uninitsWhenFalse;
1200:                    uninitsWhenFalse = uninitsWhenTrue;
1201:                    uninitsWhenTrue = t;
1202:                    break;
1203:                case JCTree.PREINC:
1204:                case JCTree.POSTINC:
1205:                case JCTree.PREDEC:
1206:                case JCTree.POSTDEC:
1207:                    scanExpr(tree.arg);
1208:                    letInit(tree.arg);
1209:                    break;
1210:                default:
1211:                    scanExpr(tree.arg);
1212:                }
1213:            }
1214:
1215:            public void visitBinary(JCBinary tree) {
1216:                switch (tree.getTag()) {
1217:                case JCTree.AND:
1218:                    scanCond(tree.lhs);
1219:                    Bits initsWhenFalseLeft = initsWhenFalse;
1220:                    Bits uninitsWhenFalseLeft = uninitsWhenFalse;
1221:                    inits = initsWhenTrue;
1222:                    uninits = uninitsWhenTrue;
1223:                    scanCond(tree.rhs);
1224:                    initsWhenFalse.andSet(initsWhenFalseLeft);
1225:                    uninitsWhenFalse.andSet(uninitsWhenFalseLeft);
1226:                    break;
1227:                case JCTree.OR:
1228:                    scanCond(tree.lhs);
1229:                    Bits initsWhenTrueLeft = initsWhenTrue;
1230:                    Bits uninitsWhenTrueLeft = uninitsWhenTrue;
1231:                    inits = initsWhenFalse;
1232:                    uninits = uninitsWhenFalse;
1233:                    scanCond(tree.rhs);
1234:                    initsWhenTrue.andSet(initsWhenTrueLeft);
1235:                    uninitsWhenTrue.andSet(uninitsWhenTrueLeft);
1236:                    break;
1237:                default:
1238:                    scanExpr(tree.lhs);
1239:                    scanExpr(tree.rhs);
1240:                }
1241:            }
1242:
1243:            public void visitIdent(JCIdent tree) {
1244:                if (tree.sym.kind == VAR)
1245:                    checkInit(tree.pos(), (VarSymbol) tree.sym);
1246:            }
1247:
1248:            public void visitTypeCast(JCTypeCast tree) {
1249:                super .visitTypeCast(tree);
1250:                if (!tree.type.isErroneous()
1251:                        && lint.isEnabled(Lint.LintCategory.CAST)
1252:                        && types.isSameType(tree.expr.type, tree.clazz.type)) {
1253:                    log.warning(tree.pos(), "redundant.cast", tree.expr.type);
1254:                }
1255:            }
1256:
1257:            public void visitTopLevel(JCCompilationUnit tree) {
1258:                // Do nothing for TopLevel since each class is visited individually
1259:            }
1260:
1261:            /**************************************************************************
1262:             * main method
1263:             *************************************************************************/
1264:
1265:            /** Perform definite assignment/unassignment analysis on a tree.
1266:             */
1267:            public void analyzeTree(JCTree tree, TreeMaker make) {
1268:                try {
1269:                    this .make = make;
1270:                    inits = new Bits();
1271:                    uninits = new Bits();
1272:                    uninitsTry = new Bits();
1273:                    initsWhenTrue = initsWhenFalse = uninitsWhenTrue = uninitsWhenFalse = null;
1274:                    if (vars == null)
1275:                        vars = new VarSymbol[32];
1276:                    else
1277:                        for (int i = 0; i < vars.length; i++)
1278:                            vars[i] = null;
1279:                    firstadr = 0;
1280:                    nextadr = 0;
1281:                    pendingExits = new ListBuffer<PendingExit>();
1282:                    alive = true;
1283:                    this .thrown = this .caught = null;
1284:                    this .classDef = null;
1285:                    scan(tree);
1286:                } finally {
1287:                    // note that recursive invocations of this method fail hard
1288:                    inits = uninits = uninitsTry = null;
1289:                    initsWhenTrue = initsWhenFalse = uninitsWhenTrue = uninitsWhenFalse = null;
1290:                    if (vars != null)
1291:                        for (int i = 0; i < vars.length; i++)
1292:                            vars[i] = null;
1293:                    firstadr = 0;
1294:                    nextadr = 0;
1295:                    pendingExits = null;
1296:                    this.make = null;
1297:                    this.thrown = this.caught = null;
1298:                    this.classDef = null;
1299:                }
1300:            }
1301:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.