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);
|