568 * its symbol. Return the class definition's symbol. |
568 * its symbol. Return the class definition's symbol. |
569 * and create |
569 * and create |
570 * @param flags The class symbol's flags |
570 * @param flags The class symbol's flags |
571 * @param owner The class symbol's owner |
571 * @param owner The class symbol's owner |
572 */ |
572 */ |
573 ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) { |
573 JCClassDecl makeEmptyClass(long flags, ClassSymbol owner) { |
|
574 return makeEmptyClass(flags, owner, null, true); |
|
575 } |
|
576 |
|
577 JCClassDecl makeEmptyClass(long flags, ClassSymbol owner, Name flatname, |
|
578 boolean addToDefs) { |
574 // Create class symbol. |
579 // Create class symbol. |
575 ClassSymbol c = reader.defineClass(names.empty, owner); |
580 ClassSymbol c = reader.defineClass(names.empty, owner); |
576 c.flatname = chk.localClassName(c); |
581 if (flatname != null) { |
|
582 c.flatname = flatname; |
|
583 } else { |
|
584 c.flatname = chk.localClassName(c); |
|
585 } |
577 c.sourcefile = owner.sourcefile; |
586 c.sourcefile = owner.sourcefile; |
578 c.completer = null; |
587 c.completer = null; |
579 c.members_field = new Scope(c); |
588 c.members_field = new Scope(c); |
580 c.flags_field = flags; |
589 c.flags_field = flags; |
581 ClassType ctype = (ClassType) c.type; |
590 ClassType ctype = (ClassType) c.type; |
704 /** Anon inner classes are used as access constructor tags. |
712 /** Anon inner classes are used as access constructor tags. |
705 * accessConstructorTag will use an existing anon class if one is available, |
713 * accessConstructorTag will use an existing anon class if one is available, |
706 * and synthethise a class (with makeEmptyClass) if one is not available. |
714 * and synthethise a class (with makeEmptyClass) if one is not available. |
707 * However, there is a small possibility that an existing class will not |
715 * However, there is a small possibility that an existing class will not |
708 * be generated as expected if it is inside a conditional with a constant |
716 * be generated as expected if it is inside a conditional with a constant |
709 * expression. If that is found to be the case, create an empty class here. |
717 * expression. If that is found to be the case, create an empty class tree here. |
710 */ |
718 */ |
711 private void checkAccessConstructorTags() { |
719 private void checkAccessConstructorTags() { |
712 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) { |
720 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) { |
713 ClassSymbol c = l.head; |
721 ClassSymbol c = l.head; |
714 if (isTranslatedClassAvailable(c)) |
722 if (isTranslatedClassAvailable(c)) |
715 continue; |
723 continue; |
716 // Create class definition tree. |
724 // Create class definition tree. |
717 JCClassDecl cdef = make.ClassDef( |
725 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC, |
718 make.Modifiers(STATIC | SYNTHETIC), names.empty, |
726 c.outermostClass(), c.flatname, false); |
719 List.<JCTypeParameter>nil(), |
727 swapAccessConstructorTag(c, cdec.sym); |
720 null, List.<JCExpression>nil(), List.<JCTree>nil()); |
728 translated.append(cdec); |
721 cdef.sym = c; |
|
722 cdef.type = c.type; |
|
723 // add it to the list of classes to be generated |
|
724 translated.append(cdef); |
|
725 } |
729 } |
726 } |
730 } |
727 // where |
731 // where |
728 private boolean isTranslatedClassAvailable(ClassSymbol c) { |
732 private boolean isTranslatedClassAvailable(ClassSymbol c) { |
729 for (JCTree tree: translated) { |
733 for (JCTree tree: translated) { |
731 && ((JCClassDecl) tree).sym == c) { |
735 && ((JCClassDecl) tree).sym == c) { |
732 return true; |
736 return true; |
733 } |
737 } |
734 } |
738 } |
735 return false; |
739 return false; |
|
740 } |
|
741 |
|
742 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) { |
|
743 for (MethodSymbol methodSymbol : accessConstrs.values()) { |
|
744 Assert.check(methodSymbol.type.hasTag(METHOD)); |
|
745 MethodType oldMethodType = |
|
746 (MethodType)methodSymbol.type; |
|
747 if (oldMethodType.argtypes.head.tsym == oldCTag) |
|
748 methodSymbol.type = |
|
749 types.createMethodTypeWithParameters(oldMethodType, |
|
750 oldMethodType.getParameterTypes().tail |
|
751 .prepend(newCTag.erasure(types))); |
|
752 } |
736 } |
753 } |
737 |
754 |
738 /************************************************************************** |
755 /************************************************************************** |
739 * Access methods |
756 * Access methods |
740 *************************************************************************/ |
757 *************************************************************************/ |
1426 while (owner.kind == TYP && ((ClassSymbol)owner).members().lookup(result).scope != null) |
1443 while (owner.kind == TYP && ((ClassSymbol)owner).members().lookup(result).scope != null) |
1427 result = names.fromString(result.toString() + target.syntheticNameChar()); |
1444 result = names.fromString(result.toString() + target.syntheticNameChar()); |
1428 return result; |
1445 return result; |
1429 } |
1446 } |
1430 |
1447 |
1431 /** Definition for this$n field. |
1448 private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) { |
1432 * @param pos The source code position of the definition. |
|
1433 * @param owner The class in which the definition goes. |
|
1434 */ |
|
1435 JCVariableDecl outerThisDef(int pos, Symbol owner) { |
|
1436 long flags = FINAL | SYNTHETIC; |
|
1437 if (owner.kind == TYP && |
1449 if (owner.kind == TYP && |
1438 target.usePrivateSyntheticFields()) |
1450 target.usePrivateSyntheticFields()) |
1439 flags |= PRIVATE; |
1451 flags |= PRIVATE; |
1440 Type target = types.erasure(owner.enclClass().type.getEnclosingType()); |
1452 Type target = types.erasure(owner.enclClass().type.getEnclosingType()); |
1441 VarSymbol outerThis = new VarSymbol( |
1453 VarSymbol outerThis = |
1442 flags, outerThisName(target, owner), target, owner); |
1454 new VarSymbol(flags, outerThisName(target, owner), target, owner); |
1443 outerThisStack = outerThisStack.prepend(outerThis); |
1455 outerThisStack = outerThisStack.prepend(outerThis); |
1444 JCVariableDecl vd = make.at(pos).VarDef(outerThis, null); |
1456 return outerThis; |
|
1457 } |
|
1458 |
|
1459 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) { |
|
1460 JCVariableDecl vd = make.at(pos).VarDef(sym, null); |
1445 vd.vartype = access(vd.vartype); |
1461 vd.vartype = access(vd.vartype); |
1446 return vd; |
1462 return vd; |
|
1463 } |
|
1464 |
|
1465 /** Definition for this$n field. |
|
1466 * @param pos The source code position of the definition. |
|
1467 * @param owner The method in which the definition goes. |
|
1468 */ |
|
1469 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) { |
|
1470 ClassSymbol c = owner.enclClass(); |
|
1471 boolean isMandated = |
|
1472 // Anonymous constructors |
|
1473 (owner.isConstructor() && owner.isAnonymous()) || |
|
1474 // Constructors of non-private inner member classes |
|
1475 (owner.isConstructor() && c.isInner() && |
|
1476 !c.isPrivate() && !c.isStatic()); |
|
1477 long flags = |
|
1478 FINAL | (isMandated ? MANDATED : SYNTHETIC); |
|
1479 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags); |
|
1480 owner.extraParams = owner.extraParams.prepend(outerThis); |
|
1481 return makeOuterThisVarDecl(pos, outerThis); |
|
1482 } |
|
1483 |
|
1484 /** Definition for this$n field. |
|
1485 * @param pos The source code position of the definition. |
|
1486 * @param owner The class in which the definition goes. |
|
1487 */ |
|
1488 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) { |
|
1489 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC); |
|
1490 return makeOuterThisVarDecl(pos, outerThis); |
1447 } |
1491 } |
1448 |
1492 |
1449 /** Return a list of trees that load the free variables in given list, |
1493 /** Return a list of trees that load the free variables in given list, |
1450 * in reverse order. |
1494 * in reverse order. |
1451 * @param pos The source code position to be used for the trees. |
1495 * @param pos The source code position to be used for the trees. |
1776 Scope s = clazz.members(); |
1820 Scope s = clazz.members(); |
1777 for (Scope.Entry e = s.elems; e != null; e = e.sibling) |
1821 for (Scope.Entry e = s.elems; e != null; e = e.sibling) |
1778 if (e.sym.kind == TYP && |
1822 if (e.sym.kind == TYP && |
1779 e.sym.name == names.empty && |
1823 e.sym.name == names.empty && |
1780 (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; |
1824 (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; |
1781 return makeEmptyClass(STATIC | SYNTHETIC, clazz); |
1825 return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym; |
1782 } |
1826 } |
1783 |
1827 |
1784 /** Return symbol for "class$" method. If there is no method definition |
1828 /** Return symbol for "class$" method. If there is no method definition |
1785 * for class$, construct one as follows: |
1829 * for class$, construct one as follows: |
1786 * |
1830 * |
2549 JCVariableDecl nameParam = make_at(tree.pos()). |
2593 JCVariableDecl nameParam = make_at(tree.pos()). |
2550 Param(names.fromString(target.syntheticNameChar() + |
2594 Param(names.fromString(target.syntheticNameChar() + |
2551 "enum" + target.syntheticNameChar() + "name"), |
2595 "enum" + target.syntheticNameChar() + "name"), |
2552 syms.stringType, tree.sym); |
2596 syms.stringType, tree.sym); |
2553 nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC; |
2597 nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC; |
2554 |
|
2555 JCVariableDecl ordParam = make. |
2598 JCVariableDecl ordParam = make. |
2556 Param(names.fromString(target.syntheticNameChar() + |
2599 Param(names.fromString(target.syntheticNameChar() + |
2557 "enum" + target.syntheticNameChar() + |
2600 "enum" + target.syntheticNameChar() + |
2558 "ordinal"), |
2601 "ordinal"), |
2559 syms.intType, tree.sym); |
2602 syms.intType, tree.sym); |
2560 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC; |
2603 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC; |
2561 |
2604 |
2562 tree.params = tree.params.prepend(ordParam).prepend(nameParam); |
2605 tree.params = tree.params.prepend(ordParam).prepend(nameParam); |
2563 |
2606 |
2564 MethodSymbol m = tree.sym; |
2607 MethodSymbol m = tree.sym; |
|
2608 m.extraParams = m.extraParams.prepend(ordParam.sym); |
|
2609 m.extraParams = m.extraParams.prepend(nameParam.sym); |
2565 Type olderasure = m.erasure(types); |
2610 Type olderasure = m.erasure(types); |
2566 m.erasure_field = new MethodType( |
2611 m.erasure_field = new MethodType( |
2567 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType), |
2612 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType), |
2568 olderasure.getReturnType(), |
2613 olderasure.getReturnType(), |
2569 olderasure.getThrownTypes(), |
2614 olderasure.getThrownTypes(), |
3047 result = tree; |
3092 result = tree; |
3048 } |
3093 } |
3049 } |
3094 } |
3050 |
3095 |
3051 public void visitAssignop(final JCAssignOp tree) { |
3096 public void visitAssignop(final JCAssignOp tree) { |
3052 if (!tree.lhs.type.isPrimitive() && |
3097 final boolean boxingReq = !tree.lhs.type.isPrimitive() && |
3053 tree.operator.type.getReturnType().isPrimitive()) { |
3098 tree.operator.type.getReturnType().isPrimitive(); |
3054 // boxing required; need to rewrite as x = (unbox typeof x)(x op y); |
3099 |
3055 // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) |
3100 // boxing required; need to rewrite as x = (unbox typeof x)(x op y); |
3056 // (but without recomputing x) |
3101 // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) |
3057 JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { |
3102 // (but without recomputing x) |
3058 public JCTree build(final JCTree lhs) { |
3103 JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { |
3059 JCTree.Tag newTag = tree.getTag().noAssignOp(); |
3104 public JCTree build(final JCTree lhs) { |
3060 // Erasure (TransTypes) can change the type of |
3105 JCTree.Tag newTag = tree.getTag().noAssignOp(); |
3061 // tree.lhs. However, we can still get the |
3106 // Erasure (TransTypes) can change the type of |
3062 // unerased type of tree.lhs as it is stored |
3107 // tree.lhs. However, we can still get the |
3063 // in tree.type in Attr. |
3108 // unerased type of tree.lhs as it is stored |
3064 Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), |
3109 // in tree.type in Attr. |
3065 newTag, |
3110 Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), |
3066 attrEnv, |
3111 newTag, |
3067 tree.type, |
3112 attrEnv, |
3068 tree.rhs.type); |
3113 tree.type, |
3069 JCExpression expr = (JCExpression)lhs; |
3114 tree.rhs.type); |
3070 if (expr.type != tree.type) |
3115 JCExpression expr = (JCExpression)lhs; |
3071 expr = make.TypeCast(tree.type, expr); |
3116 if (expr.type != tree.type) |
3072 JCBinary opResult = make.Binary(newTag, expr, tree.rhs); |
3117 expr = make.TypeCast(tree.type, expr); |
3073 opResult.operator = newOperator; |
3118 JCBinary opResult = make.Binary(newTag, expr, tree.rhs); |
3074 opResult.type = newOperator.type.getReturnType(); |
3119 opResult.operator = newOperator; |
3075 JCTypeCast newRhs = make.TypeCast(types.unboxedType(tree.type), |
3120 opResult.type = newOperator.type.getReturnType(); |
3076 opResult); |
3121 JCExpression newRhs = boxingReq ? |
3077 return make.Assign((JCExpression)lhs, newRhs).setType(tree.type); |
3122 make.TypeCast(types.unboxedType(tree.type), |
3078 } |
3123 opResult) : |
3079 }); |
3124 opResult; |
3080 result = translate(newTree); |
3125 return make.Assign((JCExpression)lhs, newRhs).setType(tree.type); |
3081 return; |
3126 } |
3082 } |
3127 }); |
3083 tree.lhs = translate(tree.lhs, tree); |
3128 result = translate(newTree); |
3084 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); |
|
3085 |
|
3086 // If translated left hand side is an Apply, we are |
|
3087 // seeing an access method invocation. In this case, append |
|
3088 // right hand side as last argument of the access method. |
|
3089 if (tree.lhs.hasTag(APPLY)) { |
|
3090 JCMethodInvocation app = (JCMethodInvocation)tree.lhs; |
|
3091 // if operation is a += on strings, |
|
3092 // make sure to convert argument to string |
|
3093 JCExpression rhs = (((OperatorSymbol)tree.operator).opcode == string_add) |
|
3094 ? makeString(tree.rhs) |
|
3095 : tree.rhs; |
|
3096 app.args = List.of(rhs).prependList(app.args); |
|
3097 result = app; |
|
3098 } else { |
|
3099 result = tree; |
|
3100 } |
|
3101 } |
3129 } |
3102 |
3130 |
3103 /** Lower a tree of the form e++ or e-- where e is an object type */ |
3131 /** Lower a tree of the form e++ or e-- where e is an object type */ |
3104 JCTree lowerBoxedPostop(final JCUnary tree) { |
3132 JCTree lowerBoxedPostop(final JCUnary tree) { |
3105 // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 |
3133 // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 |