< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java

Print this page

 464             }
 465         }
 466 
 467         public void visitPackageDef(JCPackageDecl tree) {
 468             // Do nothing for PackageDecl
 469         }
 470 
 471         protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
 472             if (swtch.hasTag(SWITCH_EXPRESSION)) {
 473                 JCYield brk = make.at(Position.NOPOS).Yield(make.Erroneous()
 474                                                                 .setType(swtch.type));
 475                 brk.target = swtch;
 476                 scan(brk);
 477             } else {
 478                 JCBreak brk = make.at(Position.NOPOS).Break(null);
 479                 brk.target = swtch;
 480                 scan(brk);
 481             }
 482         }
 483 
 484         // Do something with all static or non-static field initializers and initialization blocks.
 485         protected void forEachInitializer(JCClassDecl classDef, boolean isStatic, Consumer<? super JCTree> handler) {










 486             if (classDef == initScanClass)          // avoid infinite loops
 487                 return;
 488             JCClassDecl initScanClassPrev = initScanClass;
 489             initScanClass = classDef;
 490             try {
 491                 for (List<JCTree> defs = classDef.defs; defs.nonEmpty(); defs = defs.tail) {
 492                     JCTree def = defs.head;
 493 
 494                     // Don't recurse into nested classes
 495                     if (def.hasTag(CLASSDEF))
 496                         continue;
 497 
 498                     /* we need to check for flags in the symbol too as there could be cases for which implicit flags are
 499                      * represented in the symbol but not in the tree modifiers as they were not originally in the source
 500                      * code
 501                      */
 502                     boolean isDefStatic = ((TreeInfo.flags(def) | (TreeInfo.symbolFor(def) == null ? 0 : TreeInfo.symbolFor(def).flags_field)) & STATIC) != 0;
 503                     if (!def.hasTag(METHODDEF) && (isDefStatic == isStatic))
 504                         handler.accept(def);










 505                 }
 506             } finally {
 507                 initScanClass = initScanClassPrev;
 508             }
 509         }
 510     }
 511 
 512     /**
 513      * This pass implements the first step of the dataflow analysis, namely
 514      * the liveness analysis check. This checks that every statement is reachable.
 515      * The output of this analysis pass are used by other analyzers. This analyzer
 516      * sets the 'finallyCanCompleteNormally' field in the JCTry class.
 517      */
 518     class AliveAnalyzer extends BaseAnalyzer {
 519 
 520         /** A flag that indicates whether the last statement could
 521          *  complete normally.
 522          */
 523         private Liveness alive;
 524 

2281             tree = TreeInfo.skipParens(tree);
2282             if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
2283                 Symbol sym = TreeInfo.symbol(tree);
2284                 if (sym.kind == VAR) {
2285                     letInit(tree.pos(), (VarSymbol)sym);
2286                 }
2287             }
2288         }
2289 
2290         /** Check that trackable variable is initialized.
2291          */
2292         void checkInit(DiagnosticPosition pos, VarSymbol sym) {
2293             checkInit(pos, sym, Errors.VarMightNotHaveBeenInitialized(sym));
2294         }
2295 
2296         void checkInit(DiagnosticPosition pos, VarSymbol sym, Error errkey) {
2297             if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
2298                 trackable(sym) &&
2299                 !inits.isMember(sym.adr) &&
2300                 (sym.flags_field & CLASH) == 0) {
2301                     log.error(pos, errkey);
2302                 inits.incl(sym.adr);
2303             }
2304         }
2305 
2306         /** Utility method to reset several Bits instances.
2307          */
2308         private void resetBits(Bits... bits) {
2309             for (Bits b : bits) {
2310                 b.reset();
2311             }
2312         }
2313 
2314         /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
2315          */
2316         void split(boolean setToNull) {
2317             initsWhenFalse.assign(inits);
2318             uninitsWhenFalse.assign(uninits);
2319             initsWhenTrue.assign(inits);
2320             uninitsWhenTrue.assign(uninits);
2321             if (setToNull) {

3015             }
3016         }
3017 
3018         @Override
3019         public void visitContinue(JCContinue tree) {
3020             recordExit(new AssignPendingExit(tree, inits, uninits));
3021         }
3022 
3023         @Override
3024         public void visitReturn(JCReturn tree) {
3025             scanExpr(tree.expr);
3026             recordExit(new AssignPendingExit(tree, inits, uninits));
3027         }
3028 
3029         public void visitThrow(JCThrow tree) {
3030             scanExpr(tree.expr);
3031             markDead();
3032         }
3033 
3034         public void visitApply(JCMethodInvocation tree) {








3035             scanExpr(tree.meth);
3036             scanExprs(tree.args);
3037 
3038             // Handle superclass constructor invocations
3039             if (isConstructor) {
3040 
3041                 // If super(): at this point all initialization blocks will execute
3042                 Name name = TreeInfo.name(tree.meth);
3043                 if (name == names._super) {
3044                     forEachInitializer(classDef, false, def -> {
3045                         scan(def);
3046                         clearPendingExits(false);
3047                     });
3048                 }
3049 
3050                 // If this(): at this point all final uninitialized fields will get initialized
3051                 else if (name == names._this) {
3052                     for (int address = firstadr; address < nextadr; address++) {
3053                         VarSymbol sym = vardecls[address].sym;
3054                         if (isFinalUninitializedField(sym) && !sym.isStatic())
3055                             letInit(tree.pos(), sym);
3056                     }
3057                 }
3058             }
3059         }
3060 
3061         public void visitNewClass(JCNewClass tree) {
3062             scanExpr(tree.encl);

 464             }
 465         }
 466 
 467         public void visitPackageDef(JCPackageDecl tree) {
 468             // Do nothing for PackageDecl
 469         }
 470 
 471         protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
 472             if (swtch.hasTag(SWITCH_EXPRESSION)) {
 473                 JCYield brk = make.at(Position.NOPOS).Yield(make.Erroneous()
 474                                                                 .setType(swtch.type));
 475                 brk.target = swtch;
 476                 scan(brk);
 477             } else {
 478                 JCBreak brk = make.at(Position.NOPOS).Break(null);
 479                 brk.target = swtch;
 480                 scan(brk);
 481             }
 482         }
 483 
 484         // Do something with static or non-static field initializers and initialization blocks.
 485         protected void forEachInitializer(JCClassDecl classDef, boolean isStatic, Consumer<? super JCTree> handler) {
 486             forEachInitializer(classDef, isStatic, false, handler);
 487         }
 488 
 489         /* Do something with static or non-static field initializers and initialization blocks.
 490          * the `earlyOnly` argument will determine if we will deal or not with early variable instance
 491          * initializers we want to process only those before a super() invocation and ignore them after
 492          * it.
 493          */
 494         protected void forEachInitializer(JCClassDecl classDef, boolean isStatic, boolean earlyOnly,
 495                                           Consumer<? super JCTree> handler) {
 496             if (classDef == initScanClass)          // avoid infinite loops
 497                 return;
 498             JCClassDecl initScanClassPrev = initScanClass;
 499             initScanClass = classDef;
 500             try {
 501                 for (List<JCTree> defs = classDef.defs; defs.nonEmpty(); defs = defs.tail) {
 502                     JCTree def = defs.head;
 503 
 504                     // Don't recurse into nested classes
 505                     if (def.hasTag(CLASSDEF))
 506                         continue;
 507 
 508                     /* we need to check for flags in the symbol too as there could be cases for which implicit flags are
 509                      * represented in the symbol but not in the tree modifiers as they were not originally in the source
 510                      * code
 511                      */
 512                     boolean isDefStatic = ((TreeInfo.flags(def) | (TreeInfo.symbolFor(def) == null ? 0 : TreeInfo.symbolFor(def).flags_field)) & STATIC) != 0;
 513                     if (!def.hasTag(METHODDEF) && (isDefStatic == isStatic)) {
 514                         if (def instanceof JCVariableDecl varDecl) {
 515                             boolean isEarly = varDecl.init != null &&
 516                                     varDecl.sym.owner.isValueClass() &&
 517                                     !varDecl.sym.isStatic();
 518                             if (isEarly == earlyOnly) {
 519                                 handler.accept(def);
 520                             }
 521                         } else if (!earlyOnly) {
 522                             handler.accept(def);
 523                         }
 524                     }
 525                 }
 526             } finally {
 527                 initScanClass = initScanClassPrev;
 528             }
 529         }
 530     }
 531 
 532     /**
 533      * This pass implements the first step of the dataflow analysis, namely
 534      * the liveness analysis check. This checks that every statement is reachable.
 535      * The output of this analysis pass are used by other analyzers. This analyzer
 536      * sets the 'finallyCanCompleteNormally' field in the JCTry class.
 537      */
 538     class AliveAnalyzer extends BaseAnalyzer {
 539 
 540         /** A flag that indicates whether the last statement could
 541          *  complete normally.
 542          */
 543         private Liveness alive;
 544 

2301             tree = TreeInfo.skipParens(tree);
2302             if (tree.hasTag(IDENT) || tree.hasTag(SELECT)) {
2303                 Symbol sym = TreeInfo.symbol(tree);
2304                 if (sym.kind == VAR) {
2305                     letInit(tree.pos(), (VarSymbol)sym);
2306                 }
2307             }
2308         }
2309 
2310         /** Check that trackable variable is initialized.
2311          */
2312         void checkInit(DiagnosticPosition pos, VarSymbol sym) {
2313             checkInit(pos, sym, Errors.VarMightNotHaveBeenInitialized(sym));
2314         }
2315 
2316         void checkInit(DiagnosticPosition pos, VarSymbol sym, Error errkey) {
2317             if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
2318                 trackable(sym) &&
2319                 !inits.isMember(sym.adr) &&
2320                 (sym.flags_field & CLASH) == 0) {
2321                 log.error(pos, errkey);
2322                 inits.incl(sym.adr);
2323             }
2324         }
2325 
2326         /** Utility method to reset several Bits instances.
2327          */
2328         private void resetBits(Bits... bits) {
2329             for (Bits b : bits) {
2330                 b.reset();
2331             }
2332         }
2333 
2334         /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
2335          */
2336         void split(boolean setToNull) {
2337             initsWhenFalse.assign(inits);
2338             uninitsWhenFalse.assign(uninits);
2339             initsWhenTrue.assign(inits);
2340             uninitsWhenTrue.assign(uninits);
2341             if (setToNull) {

3035             }
3036         }
3037 
3038         @Override
3039         public void visitContinue(JCContinue tree) {
3040             recordExit(new AssignPendingExit(tree, inits, uninits));
3041         }
3042 
3043         @Override
3044         public void visitReturn(JCReturn tree) {
3045             scanExpr(tree.expr);
3046             recordExit(new AssignPendingExit(tree, inits, uninits));
3047         }
3048 
3049         public void visitThrow(JCThrow tree) {
3050             scanExpr(tree.expr);
3051             markDead();
3052         }
3053 
3054         public void visitApply(JCMethodInvocation tree) {
3055             Name name = TreeInfo.name(tree.meth);
3056             // let's process early initializers
3057             if (name == names._super) {
3058                 forEachInitializer(classDef, false, true, def -> {
3059                     scan(def);
3060                     clearPendingExits(false);
3061                 });
3062             }
3063             scanExpr(tree.meth);
3064             scanExprs(tree.args);
3065 
3066             // Handle superclass constructor invocations
3067             if (isConstructor) {
3068 
3069                 // If super(): at this point all initialization blocks will execute
3070 
3071                 if (name == names._super) {
3072                     forEachInitializer(classDef, false, def -> {
3073                         scan(def);
3074                         clearPendingExits(false);
3075                     });
3076                 }
3077 
3078                 // If this(): at this point all final uninitialized fields will get initialized
3079                 else if (name == names._this) {
3080                     for (int address = firstadr; address < nextadr; address++) {
3081                         VarSymbol sym = vardecls[address].sym;
3082                         if (isFinalUninitializedField(sym) && !sym.isStatic())
3083                             letInit(tree.pos(), sym);
3084                     }
3085                 }
3086             }
3087         }
3088 
3089         public void visitNewClass(JCNewClass tree) {
3090             scanExpr(tree.encl);
< prev index next >