< prev index next >

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

Print this page

1117             sym.owner.enclClass() != currentClass) {
1118             // A constant is replaced by its constant value.
1119             Object cv = ((VarSymbol)sym).getConstValue();
1120             if (cv != null) {
1121                 make.at(tree.pos);
1122                 return makeLit(sym.type, cv);
1123             }
1124             if (lambdaTranslationMap != null && lambdaTranslationMap.get(sym) != null) {
1125                 return make.at(tree.pos).Ident(lambdaTranslationMap.get(sym));
1126             } else {
1127                 // Otherwise replace the variable by its proxy.
1128                 sym = proxies.get(sym);
1129                 Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
1130                 tree = make.at(tree.pos).Ident(sym);
1131             }
1132         }
1133         JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
1134         switch (sym.kind) {
1135         case TYP:
1136             if (sym.owner.kind != PCK) {



1137                 // Convert type idents to
1138                 // <flat name> or <package name> . <flat name>
1139                 Name flatname = Convert.shortName(sym.flatName());
1140                 while (base != null &&
1141                        TreeInfo.symbol(base) != null &&
1142                        TreeInfo.symbol(base).kind != PCK) {
1143                     base = (base.hasTag(SELECT))
1144                         ? ((JCFieldAccess) base).selected
1145                         : null;
1146                 }
1147                 if (tree.hasTag(IDENT)) {
1148                     ((JCIdent) tree).name = flatname;
1149                 } else if (base == null) {
1150                     tree = make.at(tree.pos).Ident(sym);
1151                     ((JCIdent) tree).name = flatname;



1152                 } else {
1153                     ((JCFieldAccess) tree).selected = base;
1154                     ((JCFieldAccess) tree).name = flatname;



1155                 }
1156             }
1157             break;
1158         case MTH: case VAR:
1159             if (sym.owner.kind == TYP) {
1160 
1161                 // Access methods are required for
1162                 //  - private members,
1163                 //  - protected members in a superclass of an
1164                 //    enclosing class contained in another package.
1165                 //  - all non-private members accessed via a qualified super.
1166                 boolean protAccess = refSuper && !needsPrivateAccess(sym)
1167                     || needsProtectedAccess(sym, tree);
1168                 boolean accReq = protAccess || needsPrivateAccess(sym);
1169 
1170                 // A base has to be supplied for
1171                 //  - simple identifiers accessing variables in outer classes.
1172                 boolean baseReq =
1173                     base == null &&
1174                     sym.owner != syms.predefClass &&

1439      *  @param pos        The source code position of the definition.
1440      *  @param freevars   The free variables.
1441      *  @param owner      The class in which the definitions go.
1442      */
1443     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1444         return freevarDefs(pos, freevars, owner, 0);
1445     }
1446 
1447     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1448             long additionalFlags) {
1449         long flags = FINAL | SYNTHETIC | additionalFlags;
1450         List<JCVariableDecl> defs = List.nil();
1451         Set<Name> proxyNames = new HashSet<>();
1452         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1453             VarSymbol v = l.head;
1454             int index = 0;
1455             Name proxyName;
1456             do {
1457                 proxyName = proxyName(v.name, index++);
1458             } while (!proxyNames.add(proxyName));

1459             VarSymbol proxy = new VarSymbol(
1460                 flags, proxyName, v.erasure(types), owner);
1461             proxies.put(v, proxy);
1462             JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1463             vd.vartype = access(vd.vartype);
1464             defs = defs.prepend(vd);
1465         }
1466         return defs;
1467     }
1468 
1469     /** The name of a this$n field
1470      *  @param type   The class referenced by the this$n field
1471      */
1472     Name outerThisName(Type type, Symbol owner) {
1473         Type t = type.getEnclosingType();
1474         int nestingLevel = 0;
1475         while (t.hasTag(CLASS)) {
1476             t = t.getEnclosingType();
1477             nestingLevel++;
1478         }
1479         Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
1480         while (owner.kind == TYP && ((ClassSymbol)owner).members().findFirst(result) != null)

1507     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1508         ClassSymbol c = owner.enclClass();
1509         boolean isMandated =
1510             // Anonymous constructors
1511             (owner.isConstructor() && owner.isAnonymous()) ||
1512             // Constructors of non-private inner member classes
1513             (owner.isConstructor() && c.isInner() &&
1514              !c.isPrivate() && !c.isStatic());
1515         long flags =
1516             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1517         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1518         owner.extraParams = owner.extraParams.prepend(outerThis);
1519         return makeOuterThisVarDecl(pos, outerThis);
1520     }
1521 
1522     /** Definition for this$n field.
1523      *  @param pos        The source code position of the definition.
1524      *  @param owner      The class in which the definition goes.
1525      */
1526     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1527         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);


1528         return makeOuterThisVarDecl(pos, outerThis);
1529     }
1530 
1531     /** Return a list of trees that load the free variables in given list,
1532      *  in reverse order.
1533      *  @param pos          The source code position to be used for the trees.
1534      *  @param freevars     The list of free variables.
1535      */
1536     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1537         List<JCExpression> args = List.nil();
1538         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1539             args = args.prepend(loadFreevar(pos, l.head));
1540         return args;
1541     }
1542 //where
1543         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1544             return access(v, make.at(pos).Ident(v), null, false);
1545         }
1546 
1547     /** Construct a tree simulating the expression {@code C.this}.

1690         }
1691 
1692         JCStatement exceptionalRethrow = make.Throw(make.Ident(primaryException));
1693         JCBlock exceptionalCloseBlock = make.Block(0L, List.of(exceptionalCloseStatement, exceptionalRethrow));
1694         JCCatch exceptionalCatchClause = make.Catch(primaryExceptionDecl, exceptionalCloseBlock);
1695 
1696         //create the main try statement with the close:
1697         JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1698                                   List.of(exceptionalCatchClause),
1699                                   finallyClause);
1700 
1701         outerTry.finallyCanCompleteNormally = true;
1702         stats.add(outerTry);
1703 
1704         JCBlock newBlock = make.Block(0L, stats.toList());
1705         return newBlock;
1706     }
1707 
1708     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1709         // convert to AutoCloseable if needed
1710         if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
1711             resource = convert(resource, syms.autoCloseableType);
1712         }
1713 
1714         // create resource.close() method invocation
1715         JCExpression resourceClose = makeCall(resource,
1716                                               names.close,
1717                                               List.nil());
1718         return make.Exec(resourceClose);
1719     }
1720 
1721     private JCExpression makeNonNullCheck(JCExpression expression) {
1722         return makeBinary(NE, expression, makeNull());
1723     }
1724 
1725     /** Construct a tree that represents the outer instance
1726      *  {@code C.this}. Never pick the current `this'.
1727      *  @param pos           The source code position to be used for the tree.
1728      *  @param c             The qualifier class.
1729      */
1730     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {

2074     /** Visitor method: Translate a single node.
2075      *  Attach the source position from the old tree to its replacement tree.
2076      */
2077     @Override
2078     public <T extends JCTree> T translate(T tree) {
2079         if (tree == null) {
2080             return null;
2081         } else {
2082             make_at(tree.pos());
2083             T result = super.translate(tree);
2084             if (endPosTable != null && result != tree) {
2085                 endPosTable.replaceTree(tree, result);
2086             }
2087             return result;
2088         }
2089     }
2090 
2091     /** Visitor method: Translate a single node, boxing or unboxing if needed.
2092      */
2093     public <T extends JCExpression> T translate(T tree, Type type) {
2094         return (tree == null) ? null : boxIfNeeded(translate(tree), type);

2095     }
2096 
2097     /** Visitor method: Translate tree.
2098      */
2099     public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
2100         JCExpression prevEnclOp = this.enclOp;
2101         this.enclOp = enclOp;
2102         T res = translate(tree);
2103         this.enclOp = prevEnclOp;
2104         return res;
2105     }
2106 
2107     /** Visitor method: Translate list of trees.
2108      */
2109     public <T extends JCExpression> List<T> translate(List<T> trees, Type type) {
2110         if (trees == null) return null;
2111         for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2112             l.head = translate(l.head, type);
2113         return trees;
2114     }

2213             encl.trans_local = encl.trans_local.prepend(currentClass);
2214         }
2215 
2216         // Recursively translate members, taking into account that new members
2217         // might be created during the translation and prepended to the member
2218         // list `tree.defs'.
2219         List<JCTree> seen = List.nil();
2220         while (tree.defs != seen) {
2221             List<JCTree> unseen = tree.defs;
2222             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2223                 JCTree outermostMemberDefPrev = outermostMemberDef;
2224                 if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
2225                 l.head = translate(l.head);
2226                 outermostMemberDef = outermostMemberDefPrev;
2227             }
2228             seen = unseen;
2229         }
2230 
2231         // Convert a protected modifier to public, mask static modifier.
2232         if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
2233         tree.mods.flags &= ClassFlags;
2234 
2235         // Convert name to flat representation, replacing '.' by '$'.
2236         tree.name = Convert.shortName(currentClass.flatName());
2237 
2238         // Add free variables proxy definitions to class.
2239 
2240         for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2241             tree.defs = tree.defs.prepend(l.head);
2242             enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
2243         }
2244         // If this$n was accessed, add the field definition and
2245         // update initial constructors to initialize it
2246         if (currentClass.hasOuterInstance() && shouldEmitOuterThis(currentClass)) {
2247             tree.defs = tree.defs.prepend(otdef);
2248             enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2249 
2250            for (JCTree def : tree.defs) {
2251                 if (TreeInfo.isInitialConstructor(def)) {
2252                   JCMethodDecl mdef = (JCMethodDecl) def;
2253                   mdef.body.stats = mdef.body.stats.prepend(

3092             while (args.nonEmpty()) {
3093                 JCExpression arg = translate(args.head, varargsElement);
3094                 elems.append(arg);
3095                 args = args.tail;
3096             }
3097             JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
3098                                                List.nil(),
3099                                                elems.toList());
3100             boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
3101             result.append(boxedArgs);
3102         } else {
3103             if (args.length() != 1) throw new AssertionError(args);
3104             JCExpression arg = translate(args.head, parameter);
3105             anyChanges |= (arg != args.head);
3106             result.append(arg);
3107             if (!anyChanges) return _args;
3108         }
3109         return result.toList();
3110     }
3111 














3112     /** Expand a boxing or unboxing conversion if needed. */
3113     @SuppressWarnings("unchecked") // XXX unchecked
3114     <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
3115         boolean havePrimitive = tree.type.isPrimitive();
3116         if (havePrimitive == type.isPrimitive())
3117             return tree;
3118         if (havePrimitive) {
3119             Type unboxedTarget = types.unboxedType(type);
3120             if (!unboxedTarget.hasTag(NONE)) {
3121                 if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
3122                     tree.type = unboxedTarget.constType(tree.type.constValue());
3123                 return (T)boxPrimitive(tree, types.erasure(type));
3124             } else {
3125                 tree = (T)boxPrimitive(tree);
3126             }
3127         } else {
3128             tree = (T)unbox(tree, type);
3129         }
3130         return tree;
3131     }

3490          * A statement of the form
3491          *
3492          * <pre>
3493          *     for ( T v : coll ) stmt ;
3494          * </pre>
3495          *
3496          * (where coll implements {@code Iterable<? extends T>}) gets translated to
3497          *
3498          * <pre>{@code
3499          *     for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
3500          *         T v = (T) #i.next();
3501          *         stmt;
3502          *     }
3503          * }</pre>
3504          *
3505          * where #i is a freshly named synthetic local variable.
3506          */
3507         private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
3508             make_at(tree.expr.pos());
3509             Type iteratorTarget = syms.objectType;
3510             Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
3511                                               syms.iterableType.tsym);
3512             if (iterableType.getTypeArguments().nonEmpty())
3513                 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
3514             Type eType = types.skipTypeVars(tree.expr.type, false);
3515             tree.expr.type = types.erasure(eType);
3516             if (eType.isCompound())
3517                 tree.expr = make.TypeCast(types.erasure(iterableType), tree.expr);
3518             Symbol iterator = lookupMethod(tree.expr.pos(),
3519                                            names.iterator,
3520                                            eType,
3521                                            List.nil());
3522             VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
3523                                             types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)),
3524                                             currentMethodSym);
3525 
3526              JCStatement init = make.
3527                 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
3528                      .setType(types.erasure(iterator.type))));
3529 
3530             Symbol hasNext = lookupMethod(tree.expr.pos(),
3531                                           names.hasNext,
3532                                           itvar.type,
3533                                           List.nil());
3534             JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
3535             Symbol next = lookupMethod(tree.expr.pos(),
3536                                        names.next,
3537                                        itvar.type,
3538                                        List.nil());
3539             JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
3540             if (tree.var.type.isPrimitive())
3541                 vardefinit = make.TypeCast(types.cvarUpperBound(iteratorTarget), vardefinit);
3542             else
3543                 vardefinit = make.TypeCast(tree.var.type, vardefinit);

3580                 new MethodSymbol(tree.flags | BLOCK,
3581                                  names.empty, null,
3582                                  currentClass);
3583         }
3584         super.visitBlock(tree);
3585         currentMethodSym = oldMethodSym;
3586     }
3587 
3588     public void visitDoLoop(JCDoWhileLoop tree) {
3589         tree.body = translate(tree.body);
3590         tree.cond = translate(tree.cond, syms.booleanType);
3591         result = tree;
3592     }
3593 
3594     public void visitWhileLoop(JCWhileLoop tree) {
3595         tree.cond = translate(tree.cond, syms.booleanType);
3596         tree.body = translate(tree.body);
3597         result = tree;
3598     }
3599 

















3600     public void visitForLoop(JCForLoop tree) {
3601         tree.init = translate(tree.init);
3602         if (tree.cond != null)
3603             tree.cond = translate(tree.cond, syms.booleanType);
3604         tree.step = translate(tree.step);
3605         tree.body = translate(tree.body);
3606         result = tree;
3607     }
3608 
3609     public void visitReturn(JCReturn tree) {
3610         if (tree.expr != null)
3611             tree.expr = translate(tree.expr,
3612                                   types.erasure(currentMethodDef
3613                                                 .restype.type));
3614         result = tree;
3615     }
3616 
3617     public void visitSwitch(JCSwitch tree) {
3618         List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.cases) : tree.cases;
3619         handleSwitch(tree, tree.selector, cases);

4058         tree.value = translate(tree.value, tree.target.type);
4059         result = tree;
4060     }
4061 
4062     public void visitNewArray(JCNewArray tree) {
4063         tree.elemtype = translate(tree.elemtype);
4064         for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
4065             if (t.head != null) t.head = translate(t.head, syms.intType);
4066         tree.elems = translate(tree.elems, types.elemtype(tree.type));
4067         result = tree;
4068     }
4069 
4070     public void visitSelect(JCFieldAccess tree) {
4071         // need to special case-access of the form C.super.x
4072         // these will always need an access method, unless C
4073         // is a default interface subclassed by the current class.
4074         boolean qualifiedSuperAccess =
4075             tree.selected.hasTag(SELECT) &&
4076             TreeInfo.name(tree.selected) == names._super &&
4077             !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);





4078         tree.selected = translate(tree.selected);



4079         if (tree.name == names._class) {
4080             result = classOf(tree.selected);
4081         }
4082         else if (tree.name == names._super &&
4083                 types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
4084             //default super call!! Not a classic qualified super call
4085             TypeSymbol supSym = tree.selected.type.tsym;
4086             Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
4087             result = tree;
4088         }
4089         else if (tree.name == names._this || tree.name == names._super) {
4090             result = makeThis(tree.pos(), tree.selected.type.tsym);
4091         }
4092         else
4093             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
4094     }
4095 
4096     public void visitLetExpr(LetExpr tree) {
4097         tree.defs = translate(tree.defs);
4098         tree.expr = translate(tree.expr, tree.type);
4099         result = tree;
4100     }
4101 
4102     // There ought to be nothing to rewrite here;
4103     // we don't generate code.
4104     public void visitAnnotation(JCAnnotation tree) {
4105         result = tree;
4106     }

1117             sym.owner.enclClass() != currentClass) {
1118             // A constant is replaced by its constant value.
1119             Object cv = ((VarSymbol)sym).getConstValue();
1120             if (cv != null) {
1121                 make.at(tree.pos);
1122                 return makeLit(sym.type, cv);
1123             }
1124             if (lambdaTranslationMap != null && lambdaTranslationMap.get(sym) != null) {
1125                 return make.at(tree.pos).Ident(lambdaTranslationMap.get(sym));
1126             } else {
1127                 // Otherwise replace the variable by its proxy.
1128                 sym = proxies.get(sym);
1129                 Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
1130                 tree = make.at(tree.pos).Ident(sym);
1131             }
1132         }
1133         JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
1134         switch (sym.kind) {
1135         case TYP:
1136             if (sym.owner.kind != PCK) {
1137                 // Make sure not to lose type fidelity due to symbol sharing between projections
1138                 boolean requireReferenceProjection =
1139                         tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection();
1140                 // Convert type idents to
1141                 // <flat name> or <package name> . <flat name>
1142                 Name flatname = Convert.shortName(sym.flatName());
1143                 while (base != null &&
1144                        TreeInfo.symbol(base) != null &&
1145                        TreeInfo.symbol(base).kind != PCK) {
1146                     base = (base.hasTag(SELECT))
1147                         ? ((JCFieldAccess) base).selected
1148                         : null;
1149                 }
1150                 if (tree.hasTag(IDENT)) {
1151                     ((JCIdent) tree).name = flatname;
1152                 } else if (base == null) {
1153                     tree = make.at(tree.pos).Ident(sym);
1154                     ((JCIdent) tree).name = flatname;
1155                     if (requireReferenceProjection) {
1156                         tree.setType(tree.type.referenceProjection());
1157                     }
1158                 } else {
1159                     ((JCFieldAccess) tree).selected = base;
1160                     ((JCFieldAccess) tree).name = flatname;
1161                     if (requireReferenceProjection) {
1162                         tree.setType(tree.type.referenceProjection());
1163                     }
1164                 }
1165             }
1166             break;
1167         case MTH: case VAR:
1168             if (sym.owner.kind == TYP) {
1169 
1170                 // Access methods are required for
1171                 //  - private members,
1172                 //  - protected members in a superclass of an
1173                 //    enclosing class contained in another package.
1174                 //  - all non-private members accessed via a qualified super.
1175                 boolean protAccess = refSuper && !needsPrivateAccess(sym)
1176                     || needsProtectedAccess(sym, tree);
1177                 boolean accReq = protAccess || needsPrivateAccess(sym);
1178 
1179                 // A base has to be supplied for
1180                 //  - simple identifiers accessing variables in outer classes.
1181                 boolean baseReq =
1182                     base == null &&
1183                     sym.owner != syms.predefClass &&

1448      *  @param pos        The source code position of the definition.
1449      *  @param freevars   The free variables.
1450      *  @param owner      The class in which the definitions go.
1451      */
1452     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1453         return freevarDefs(pos, freevars, owner, 0);
1454     }
1455 
1456     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1457             long additionalFlags) {
1458         long flags = FINAL | SYNTHETIC | additionalFlags;
1459         List<JCVariableDecl> defs = List.nil();
1460         Set<Name> proxyNames = new HashSet<>();
1461         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1462             VarSymbol v = l.head;
1463             int index = 0;
1464             Name proxyName;
1465             do {
1466                 proxyName = proxyName(v.name, index++);
1467             } while (!proxyNames.add(proxyName));
1468             final Type type = v.erasure(types);
1469             VarSymbol proxy = new VarSymbol(
1470                 flags, proxyName, type, owner);
1471             proxies.put(v, proxy);
1472             JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1473             vd.vartype = access(vd.vartype);
1474             defs = defs.prepend(vd);
1475         }
1476         return defs;
1477     }
1478 
1479     /** The name of a this$n field
1480      *  @param type   The class referenced by the this$n field
1481      */
1482     Name outerThisName(Type type, Symbol owner) {
1483         Type t = type.getEnclosingType();
1484         int nestingLevel = 0;
1485         while (t.hasTag(CLASS)) {
1486             t = t.getEnclosingType();
1487             nestingLevel++;
1488         }
1489         Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
1490         while (owner.kind == TYP && ((ClassSymbol)owner).members().findFirst(result) != null)

1517     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1518         ClassSymbol c = owner.enclClass();
1519         boolean isMandated =
1520             // Anonymous constructors
1521             (owner.isConstructor() && owner.isAnonymous()) ||
1522             // Constructors of non-private inner member classes
1523             (owner.isConstructor() && c.isInner() &&
1524              !c.isPrivate() && !c.isStatic());
1525         long flags =
1526             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1527         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1528         owner.extraParams = owner.extraParams.prepend(outerThis);
1529         return makeOuterThisVarDecl(pos, outerThis);
1530     }
1531 
1532     /** Definition for this$n field.
1533      *  @param pos        The source code position of the definition.
1534      *  @param owner      The class in which the definition goes.
1535      */
1536     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1537         Type target = types.erasure(owner.enclClass().type.getEnclosingType());
1538         long flags = FINAL | SYNTHETIC;
1539         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1540         return makeOuterThisVarDecl(pos, outerThis);
1541     }
1542 
1543     /** Return a list of trees that load the free variables in given list,
1544      *  in reverse order.
1545      *  @param pos          The source code position to be used for the trees.
1546      *  @param freevars     The list of free variables.
1547      */
1548     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1549         List<JCExpression> args = List.nil();
1550         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1551             args = args.prepend(loadFreevar(pos, l.head));
1552         return args;
1553     }
1554 //where
1555         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1556             return access(v, make.at(pos).Ident(v), null, false);
1557         }
1558 
1559     /** Construct a tree simulating the expression {@code C.this}.

1702         }
1703 
1704         JCStatement exceptionalRethrow = make.Throw(make.Ident(primaryException));
1705         JCBlock exceptionalCloseBlock = make.Block(0L, List.of(exceptionalCloseStatement, exceptionalRethrow));
1706         JCCatch exceptionalCatchClause = make.Catch(primaryExceptionDecl, exceptionalCloseBlock);
1707 
1708         //create the main try statement with the close:
1709         JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1710                                   List.of(exceptionalCatchClause),
1711                                   finallyClause);
1712 
1713         outerTry.finallyCanCompleteNormally = true;
1714         stats.add(outerTry);
1715 
1716         JCBlock newBlock = make.Block(0L, stats.toList());
1717         return newBlock;
1718     }
1719 
1720     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1721         // convert to AutoCloseable if needed
1722         if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) {
1723             resource = convert(resource, syms.autoCloseableType);
1724         }
1725 
1726         // create resource.close() method invocation
1727         JCExpression resourceClose = makeCall(resource,
1728                                               names.close,
1729                                               List.nil());
1730         return make.Exec(resourceClose);
1731     }
1732 
1733     private JCExpression makeNonNullCheck(JCExpression expression) {
1734         return makeBinary(NE, expression, makeNull());
1735     }
1736 
1737     /** Construct a tree that represents the outer instance
1738      *  {@code C.this}. Never pick the current `this'.
1739      *  @param pos           The source code position to be used for the tree.
1740      *  @param c             The qualifier class.
1741      */
1742     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {

2086     /** Visitor method: Translate a single node.
2087      *  Attach the source position from the old tree to its replacement tree.
2088      */
2089     @Override
2090     public <T extends JCTree> T translate(T tree) {
2091         if (tree == null) {
2092             return null;
2093         } else {
2094             make_at(tree.pos());
2095             T result = super.translate(tree);
2096             if (endPosTable != null && result != tree) {
2097                 endPosTable.replaceTree(tree, result);
2098             }
2099             return result;
2100         }
2101     }
2102 
2103     /** Visitor method: Translate a single node, boxing or unboxing if needed.
2104      */
2105     public <T extends JCExpression> T translate(T tree, Type type) {
2106         return (tree == null) ? null :
2107                 applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
2108     }
2109 
2110     /** Visitor method: Translate tree.
2111      */
2112     public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
2113         JCExpression prevEnclOp = this.enclOp;
2114         this.enclOp = enclOp;
2115         T res = translate(tree);
2116         this.enclOp = prevEnclOp;
2117         return res;
2118     }
2119 
2120     /** Visitor method: Translate list of trees.
2121      */
2122     public <T extends JCExpression> List<T> translate(List<T> trees, Type type) {
2123         if (trees == null) return null;
2124         for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2125             l.head = translate(l.head, type);
2126         return trees;
2127     }

2226             encl.trans_local = encl.trans_local.prepend(currentClass);
2227         }
2228 
2229         // Recursively translate members, taking into account that new members
2230         // might be created during the translation and prepended to the member
2231         // list `tree.defs'.
2232         List<JCTree> seen = List.nil();
2233         while (tree.defs != seen) {
2234             List<JCTree> unseen = tree.defs;
2235             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2236                 JCTree outermostMemberDefPrev = outermostMemberDef;
2237                 if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
2238                 l.head = translate(l.head);
2239                 outermostMemberDef = outermostMemberDefPrev;
2240             }
2241             seen = unseen;
2242         }
2243 
2244         // Convert a protected modifier to public, mask static modifier.
2245         if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
2246         tree.mods.flags &= AdjustedClassFlags;
2247 
2248         // Convert name to flat representation, replacing '.' by '$'.
2249         tree.name = Convert.shortName(currentClass.flatName());
2250 
2251         // Add free variables proxy definitions to class.
2252 
2253         for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2254             tree.defs = tree.defs.prepend(l.head);
2255             enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
2256         }
2257         // If this$n was accessed, add the field definition and
2258         // update initial constructors to initialize it
2259         if (currentClass.hasOuterInstance() && shouldEmitOuterThis(currentClass)) {
2260             tree.defs = tree.defs.prepend(otdef);
2261             enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2262 
2263            for (JCTree def : tree.defs) {
2264                 if (TreeInfo.isInitialConstructor(def)) {
2265                   JCMethodDecl mdef = (JCMethodDecl) def;
2266                   mdef.body.stats = mdef.body.stats.prepend(

3105             while (args.nonEmpty()) {
3106                 JCExpression arg = translate(args.head, varargsElement);
3107                 elems.append(arg);
3108                 args = args.tail;
3109             }
3110             JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
3111                                                List.nil(),
3112                                                elems.toList());
3113             boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
3114             result.append(boxedArgs);
3115         } else {
3116             if (args.length() != 1) throw new AssertionError(args);
3117             JCExpression arg = translate(args.head, parameter);
3118             anyChanges |= (arg != args.head);
3119             result.append(arg);
3120             if (!anyChanges) return _args;
3121         }
3122         return result.toList();
3123     }
3124 
3125     /** Apply primitive value/reference conversions as needed */
3126     @SuppressWarnings("unchecked")
3127     <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
3128         boolean haveValue = tree.type.isPrimitiveClass();
3129         if (haveValue == type.isPrimitiveClass())
3130             return tree;
3131         // For narrowing conversion, insert a cast which should trigger a null check
3132         // For widening conversions, insert a cast if emitting a unified class file.
3133         return (T) make.TypeCast(type, tree);
3134 
3135     }
3136 
3137 
3138 
3139     /** Expand a boxing or unboxing conversion if needed. */
3140     @SuppressWarnings("unchecked") // XXX unchecked
3141     <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
3142         boolean havePrimitive = tree.type.isPrimitive();
3143         if (havePrimitive == type.isPrimitive())
3144             return tree;
3145         if (havePrimitive) {
3146             Type unboxedTarget = types.unboxedType(type);
3147             if (!unboxedTarget.hasTag(NONE)) {
3148                 if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
3149                     tree.type = unboxedTarget.constType(tree.type.constValue());
3150                 return (T)boxPrimitive(tree, types.erasure(type));
3151             } else {
3152                 tree = (T)boxPrimitive(tree);
3153             }
3154         } else {
3155             tree = (T)unbox(tree, type);
3156         }
3157         return tree;
3158     }

3517          * A statement of the form
3518          *
3519          * <pre>
3520          *     for ( T v : coll ) stmt ;
3521          * </pre>
3522          *
3523          * (where coll implements {@code Iterable<? extends T>}) gets translated to
3524          *
3525          * <pre>{@code
3526          *     for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
3527          *         T v = (T) #i.next();
3528          *         stmt;
3529          *     }
3530          * }</pre>
3531          *
3532          * where #i is a freshly named synthetic local variable.
3533          */
3534         private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
3535             make_at(tree.expr.pos());
3536             Type iteratorTarget = syms.objectType;
3537             Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()),
3538                                               syms.iterableType.tsym);
3539             if (iterableType.getTypeArguments().nonEmpty())
3540                 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
3541             Type eType = types.skipTypeVars(tree.expr.type, false);
3542             tree.expr.type = types.erasure(eType);
3543             if (eType.isCompound())
3544                 tree.expr = make.TypeCast(types.erasure(iterableType), tree.expr);
3545             Symbol iterator = lookupMethod(tree.expr.pos(),
3546                                            names.iterator,
3547                                            eType,
3548                                            List.nil());
3549             VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
3550                                             types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)),
3551                                             currentMethodSym);
3552 
3553              JCStatement init = make.
3554                 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
3555                      .setType(types.erasure(iterator.type))));
3556 
3557             Symbol hasNext = lookupMethod(tree.expr.pos(),
3558                                           names.hasNext,
3559                                           itvar.type,
3560                                           List.nil());
3561             JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
3562             Symbol next = lookupMethod(tree.expr.pos(),
3563                                        names.next,
3564                                        itvar.type,
3565                                        List.nil());
3566             JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
3567             if (tree.var.type.isPrimitive())
3568                 vardefinit = make.TypeCast(types.cvarUpperBound(iteratorTarget), vardefinit);
3569             else
3570                 vardefinit = make.TypeCast(tree.var.type, vardefinit);

3607                 new MethodSymbol(tree.flags | BLOCK,
3608                                  names.empty, null,
3609                                  currentClass);
3610         }
3611         super.visitBlock(tree);
3612         currentMethodSym = oldMethodSym;
3613     }
3614 
3615     public void visitDoLoop(JCDoWhileLoop tree) {
3616         tree.body = translate(tree.body);
3617         tree.cond = translate(tree.cond, syms.booleanType);
3618         result = tree;
3619     }
3620 
3621     public void visitWhileLoop(JCWhileLoop tree) {
3622         tree.cond = translate(tree.cond, syms.booleanType);
3623         tree.body = translate(tree.body);
3624         result = tree;
3625     }
3626 
3627     public void visitWithField(JCWithField tree) {
3628         Type fieldType = tree.field.type;
3629         tree.field = translate(tree.field, tree);
3630         tree.value = translate(tree.value, fieldType); // important to use pre-translation type.
3631 
3632         // If translated field is an Apply, we are
3633         // seeing an access method invocation. In this case, append
3634         // right hand side as last argument of the access method.
3635         if (tree.field.hasTag(APPLY)) {
3636             JCMethodInvocation app = (JCMethodInvocation) tree.field;
3637             app.args = List.of(tree.value).prependList(app.args);
3638             result = app;
3639         } else {
3640             result = tree;
3641         }
3642     }
3643 
3644     public void visitForLoop(JCForLoop tree) {
3645         tree.init = translate(tree.init);
3646         if (tree.cond != null)
3647             tree.cond = translate(tree.cond, syms.booleanType);
3648         tree.step = translate(tree.step);
3649         tree.body = translate(tree.body);
3650         result = tree;
3651     }
3652 
3653     public void visitReturn(JCReturn tree) {
3654         if (tree.expr != null)
3655             tree.expr = translate(tree.expr,
3656                                   types.erasure(currentMethodDef
3657                                                 .restype.type));
3658         result = tree;
3659     }
3660 
3661     public void visitSwitch(JCSwitch tree) {
3662         List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.cases) : tree.cases;
3663         handleSwitch(tree, tree.selector, cases);

4102         tree.value = translate(tree.value, tree.target.type);
4103         result = tree;
4104     }
4105 
4106     public void visitNewArray(JCNewArray tree) {
4107         tree.elemtype = translate(tree.elemtype);
4108         for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
4109             if (t.head != null) t.head = translate(t.head, syms.intType);
4110         tree.elems = translate(tree.elems, types.elemtype(tree.type));
4111         result = tree;
4112     }
4113 
4114     public void visitSelect(JCFieldAccess tree) {
4115         // need to special case-access of the form C.super.x
4116         // these will always need an access method, unless C
4117         // is a default interface subclassed by the current class.
4118         boolean qualifiedSuperAccess =
4119             tree.selected.hasTag(SELECT) &&
4120             TreeInfo.name(tree.selected) == names._super &&
4121             !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
4122         /* JDK-8269956: Where a reflective (class) literal is needed, the unqualified Point.class is
4123          * always the "primary" mirror - representing the primitive reference runtime type - thereby
4124          * always matching the behavior of Object::getClass
4125          */
4126         boolean needPrimaryMirror = tree.name == names._class && tree.selected.type.isReferenceProjection();
4127         tree.selected = translate(tree.selected);
4128         if (needPrimaryMirror && tree.selected.type.isPrimitiveClass()) {
4129             tree.selected.setType(tree.selected.type.referenceProjection());
4130         }
4131         if (tree.name == names._class) {
4132             result = classOf(tree.selected);
4133         }
4134         else if (tree.name == names._super &&
4135                 types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
4136             //default super call!! Not a classic qualified super call
4137             TypeSymbol supSym = tree.selected.type.tsym;
4138             Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym));
4139             result = tree;
4140         }
4141         else if (tree.name == names._this || tree.name == names._super) {
4142             result = makeThis(tree.pos(), tree.selected.type.tsym);
4143         }
4144         else
4145             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
4146     }
4147 
4148     public void visitLetExpr(LetExpr tree) {
4149         tree.defs = translate(tree.defs);
4150         tree.expr = translate(tree.expr, tree.type);
4151         result = tree;
4152     }
4153 
4154     // There ought to be nothing to rewrite here;
4155     // we don't generate code.
4156     public void visitAnnotation(JCAnnotation tree) {
4157         result = tree;
4158     }
< prev index next >