407 boolean hasFinally(JCTree target, Env<GenContext> env) {
408 while (env.tree != target) {
409 if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
410 return true;
411 env = env.next;
412 }
413 return false;
414 }
415
416 /* ************************************************************************
417 * Normalizing class-members.
418 *************************************************************************/
419
420 /** Distribute member initializer code into constructors and {@code <clinit>}
421 * method.
422 * @param defs The list of class member declarations.
423 * @param c The enclosing class.
424 */
425 List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
426 ListBuffer<JCStatement> initCode = new ListBuffer<>();
427 ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
428 ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
429 ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
430 ListBuffer<JCTree> methodDefs = new ListBuffer<>();
431 // Sort definitions into three listbuffers:
432 // - initCode for instance initializers
433 // - clinitCode for class initializers
434 // - methodDefs for method definitions
435 for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
436 JCTree def = l.head;
437 switch (def.getTag()) {
438 case BLOCK:
439 JCBlock block = (JCBlock)def;
440 if ((block.flags & STATIC) != 0)
441 clinitCode.append(block);
442 else if ((block.flags & SYNTHETIC) == 0)
443 initCode.append(block);
444 break;
445 case METHODDEF:
446 methodDefs.append(def);
447 break;
448 case VARDEF:
449 JCVariableDecl vdef = (JCVariableDecl) def;
450 VarSymbol sym = vdef.sym;
451 checkDimension(vdef.pos(), sym.type);
452 if (vdef.init != null) {
453 if ((sym.flags() & STATIC) == 0) {
454 // Always initialize instance variables.
455 JCStatement init = make.at(vdef.pos()).
456 Assignment(sym, vdef.init);
457 initCode.append(init);
458 endPosTable.replaceTree(vdef, init);
459 initTAs.addAll(getAndRemoveNonFieldTAs(sym));
460 } else if (sym.getConstValue() == null) {
461 // Initialize class (static) variables only if
462 // they are not compile-time constants.
463 JCStatement init = make.at(vdef.pos).
464 Assignment(sym, vdef.init);
465 clinitCode.append(init);
466 endPosTable.replaceTree(vdef, init);
467 clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
468 } else {
469 checkStringConstant(vdef.init.pos(), sym.getConstValue());
470 /* if the init contains a reference to an external class, add it to the
471 * constant's pool
472 */
473 vdef.init.accept(classReferenceVisitor);
474 }
475 }
476 break;
477 default:
478 Assert.error();
479 }
480 }
481 // Insert any instance initializers into all constructors.
482 if (initCode.length() != 0) {
483 List<JCStatement> inits = initCode.toList();
484 initTAs.addAll(c.getInitTypeAttributes());
485 List<Attribute.TypeCompound> initTAlist = initTAs.toList();
486 for (JCTree t : methodDefs) {
487 normalizeMethod((JCMethodDecl)t, inits, initTAlist);
488 }
489 }
490 // If there are class initializers, create a <clinit> method
491 // that contains them as its body.
492 if (clinitCode.length() != 0) {
493 MethodSymbol clinit = new MethodSymbol(
494 STATIC | (c.flags() & STRICTFP),
495 names.clinit,
496 new MethodType(
497 List.nil(), syms.voidType,
498 List.nil(), syms.methodClass),
499 c);
500 c.members().enter(clinit);
501 List<JCStatement> clinitStats = clinitCode.toList();
502 JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
503 block.endpos = TreeInfo.endPos(clinitStats.last());
504 methodDefs.append(make.MethodDef(clinit, block));
505
506 if (!clinitTAs.isEmpty())
507 clinit.appendUniqueTypeAttributes(clinitTAs.toList());
530
531 /** Check a constant value and report if it is a string that is
532 * too large.
533 */
534 private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
535 if (nerrs != 0 || // only complain about a long string once
536 constValue == null ||
537 !(constValue instanceof String str) ||
538 str.length() < PoolWriter.MAX_STRING_LENGTH)
539 return;
540 log.error(pos, Errors.LimitString);
541 nerrs++;
542 }
543
544 /** Insert instance initializer code into constructors prior to the super() call.
545 * @param md The tree potentially representing a
546 * constructor's definition.
547 * @param initCode The list of instance initializer statements.
548 * @param initTAs Type annotations from the initializer expression.
549 */
550 void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
551 if (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
552 // We are seeing a constructor that has a super() call.
553 // Find the super() invocation and append the given initializer code.
554 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));
555
556 if (md.body.endpos == Position.NOPOS)
557 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
558
559 md.sym.appendUniqueTypeAttributes(initTAs);
560 }
561 }
562
563 /* ************************************************************************
564 * Traversal methods
565 *************************************************************************/
566
567 /** Visitor argument: The current environment.
568 */
569 Env<GenContext> env;
570
571 /** Visitor argument: The expected type (prototype).
572 */
573 Type pt;
574
575 /** Visitor result: The item representing the computed value.
576 */
577 Item result;
578
579 /** Visitor method: generate code for a definition, catching and reporting
580 * any completion failures.
581 * @param tree The definition to be visited.
582 * @param env The environment current at the definition.
2356 items.makeThisItem().load();
2357 sym = binaryQualifier(sym, env.enclClass.type);
2358 result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2359 }
2360 }
2361
2362 //where
2363 private boolean nonVirtualForPrivateAccess(Symbol sym) {
2364 boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2365 !disableVirtualizedPrivateInvoke;
2366 return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2367 }
2368
2369 public void visitSelect(JCFieldAccess tree) {
2370 Symbol sym = tree.sym;
2371
2372 if (tree.name == names._class) {
2373 code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2374 result = items.makeStackItem(pt);
2375 return;
2376 }
2377
2378 Symbol ssym = TreeInfo.symbol(tree.selected);
2379
2380 // Are we selecting via super?
2381 boolean selectSuper =
2382 ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2383
2384 // Are we accessing a member of the superclass in an access method
2385 // resulting from a qualified super?
2386 boolean accessSuper = isAccessSuper(env.enclMethod);
2387
2388 Item base = (selectSuper)
2389 ? items.makeSuperItem()
2390 : genExpr(tree.selected, tree.selected.type);
2391
2392 if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2393 // We are seeing a variable that is constant but its selecting
2394 // expression is not.
2395 if ((sym.flags() & STATIC) != 0) {
2396 if (!selectSuper && (ssym == null || ssym.kind != TYP))
|
407 boolean hasFinally(JCTree target, Env<GenContext> env) {
408 while (env.tree != target) {
409 if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
410 return true;
411 env = env.next;
412 }
413 return false;
414 }
415
416 /* ************************************************************************
417 * Normalizing class-members.
418 *************************************************************************/
419
420 /** Distribute member initializer code into constructors and {@code <clinit>}
421 * method.
422 * @param defs The list of class member declarations.
423 * @param c The enclosing class.
424 */
425 List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
426 ListBuffer<JCStatement> initCode = new ListBuffer<>();
427 // only used for value classes
428 ListBuffer<JCStatement> initBlocks = new ListBuffer<>();
429 ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
430 ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
431 ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
432 ListBuffer<JCTree> methodDefs = new ListBuffer<>();
433 // Sort definitions into three listbuffers:
434 // - initCode for instance initializers
435 // - clinitCode for class initializers
436 // - methodDefs for method definitions
437 for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
438 JCTree def = l.head;
439 switch (def.getTag()) {
440 case BLOCK:
441 JCBlock block = (JCBlock)def;
442 if ((block.flags & STATIC) != 0)
443 clinitCode.append(block);
444 else if ((block.flags & SYNTHETIC) == 0) {
445 if (c.isValueClass()) {
446 initBlocks.append(block);
447 } else {
448 initCode.append(block);
449 }
450 }
451 break;
452 case METHODDEF:
453 methodDefs.append(def);
454 break;
455 case VARDEF:
456 JCVariableDecl vdef = (JCVariableDecl) def;
457 VarSymbol sym = vdef.sym;
458 checkDimension(vdef.pos(), sym.type);
459 if (vdef.init != null) {
460 if ((sym.flags() & STATIC) == 0) {
461 // Always initialize instance variables.
462 JCStatement init = make.at(vdef.pos()).
463 Assignment(sym, vdef.init);
464 initCode.append(init);
465 endPosTable.replaceTree(vdef, init);
466 initTAs.addAll(getAndRemoveNonFieldTAs(sym));
467 } else if (sym.getConstValue() == null) {
468 // Initialize class (static) variables only if
469 // they are not compile-time constants.
470 JCStatement init = make.at(vdef.pos).
471 Assignment(sym, vdef.init);
472 clinitCode.append(init);
473 endPosTable.replaceTree(vdef, init);
474 clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
475 } else {
476 checkStringConstant(vdef.init.pos(), sym.getConstValue());
477 /* if the init contains a reference to an external class, add it to the
478 * constant's pool
479 */
480 vdef.init.accept(classReferenceVisitor);
481 }
482 }
483 break;
484 default:
485 Assert.error();
486 }
487 }
488 // Insert any instance initializers into all constructors.
489 if (initCode.length() != 0 || initBlocks.length() != 0) {
490 initTAs.addAll(c.getInitTypeAttributes());
491 List<Attribute.TypeCompound> initTAlist = initTAs.toList();
492 for (JCTree t : methodDefs) {
493 normalizeMethod((JCMethodDecl)t, initCode.toList(), initBlocks.toList(), initTAlist);
494 }
495 }
496 // If there are class initializers, create a <clinit> method
497 // that contains them as its body.
498 if (clinitCode.length() != 0) {
499 MethodSymbol clinit = new MethodSymbol(
500 STATIC | (c.flags() & STRICTFP),
501 names.clinit,
502 new MethodType(
503 List.nil(), syms.voidType,
504 List.nil(), syms.methodClass),
505 c);
506 c.members().enter(clinit);
507 List<JCStatement> clinitStats = clinitCode.toList();
508 JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
509 block.endpos = TreeInfo.endPos(clinitStats.last());
510 methodDefs.append(make.MethodDef(clinit, block));
511
512 if (!clinitTAs.isEmpty())
513 clinit.appendUniqueTypeAttributes(clinitTAs.toList());
536
537 /** Check a constant value and report if it is a string that is
538 * too large.
539 */
540 private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
541 if (nerrs != 0 || // only complain about a long string once
542 constValue == null ||
543 !(constValue instanceof String str) ||
544 str.length() < PoolWriter.MAX_STRING_LENGTH)
545 return;
546 log.error(pos, Errors.LimitString);
547 nerrs++;
548 }
549
550 /** Insert instance initializer code into constructors prior to the super() call.
551 * @param md The tree potentially representing a
552 * constructor's definition.
553 * @param initCode The list of instance initializer statements.
554 * @param initTAs Type annotations from the initializer expression.
555 */
556 void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<JCStatement> initBlocks, List<TypeCompound> initTAs) {
557 if (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
558 // We are seeing a constructor that has a super() call.
559 // Find the super() invocation and append the given initializer code.
560 if (md.sym.owner.isValueClass()) {
561 rewriteInitializersIfNeeded(md, initCode);
562 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.append(supercall).appendList(initBlocks)));
563 } else {
564 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));
565 }
566
567 if (md.body.endpos == Position.NOPOS)
568 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
569
570 md.sym.appendUniqueTypeAttributes(initTAs);
571 }
572 }
573
574 void rewriteInitializersIfNeeded(JCMethodDecl md, List<JCStatement> initCode) {
575 if (lower.initializerOuterThis.containsKey(md.sym.owner)) {
576 InitializerVisitor initializerVisitor = new InitializerVisitor(md, lower.initializerOuterThis.get(md.sym.owner));
577 for (JCStatement init : initCode) {
578 initializerVisitor.scan(init);
579 }
580 }
581 }
582
583 class InitializerVisitor extends TreeScanner {
584 JCMethodDecl md;
585 Set<JCExpression> exprSet;
586
587 InitializerVisitor(JCMethodDecl md, Set<JCExpression> exprSet) {
588 this.md = md;
589 this.exprSet = exprSet;
590 }
591
592 @Override
593 public void visitTree(JCTree tree) {}
594
595 @Override
596 public void visitIdent(JCIdent tree) {
597 if (exprSet.contains(tree)) {
598 for (JCVariableDecl param: md.params) {
599 if (param.name == tree.name &&
600 ((param.sym.flags_field & (MANDATED | NOOUTERTHIS)) == (MANDATED | NOOUTERTHIS))) {
601 tree.sym = param.sym;
602 }
603 }
604 }
605 }
606 }
607
608 /* ************************************************************************
609 * Traversal methods
610 *************************************************************************/
611
612 /** Visitor argument: The current environment.
613 */
614 Env<GenContext> env;
615
616 /** Visitor argument: The expected type (prototype).
617 */
618 Type pt;
619
620 /** Visitor result: The item representing the computed value.
621 */
622 Item result;
623
624 /** Visitor method: generate code for a definition, catching and reporting
625 * any completion failures.
626 * @param tree The definition to be visited.
627 * @param env The environment current at the definition.
2401 items.makeThisItem().load();
2402 sym = binaryQualifier(sym, env.enclClass.type);
2403 result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2404 }
2405 }
2406
2407 //where
2408 private boolean nonVirtualForPrivateAccess(Symbol sym) {
2409 boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2410 !disableVirtualizedPrivateInvoke;
2411 return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2412 }
2413
2414 public void visitSelect(JCFieldAccess tree) {
2415 Symbol sym = tree.sym;
2416
2417 if (tree.name == names._class) {
2418 code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2419 result = items.makeStackItem(pt);
2420 return;
2421 }
2422
2423 Symbol ssym = TreeInfo.symbol(tree.selected);
2424
2425 // Are we selecting via super?
2426 boolean selectSuper =
2427 ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2428
2429 // Are we accessing a member of the superclass in an access method
2430 // resulting from a qualified super?
2431 boolean accessSuper = isAccessSuper(env.enclMethod);
2432
2433 Item base = (selectSuper)
2434 ? items.makeSuperItem()
2435 : genExpr(tree.selected, tree.selected.type);
2436
2437 if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2438 // We are seeing a variable that is constant but its selecting
2439 // expression is not.
2440 if ((sym.flags() & STATIC) != 0) {
2441 if (!selectSuper && (ssym == null || ssym.kind != TYP))
|