85
86 private final Names names;
87 private final Log log;
88 private final Symtab syms;
89 private final Resolve rs;
90 private final Operators operators;
91 private final Check chk;
92 private final Attr attr;
93 private TreeMaker make;
94 private DiagnosticPosition make_pos;
95 private final ConstFold cfolder;
96 private final Target target;
97 private final TypeEnvs typeEnvs;
98 private final Name dollarAssertionsDisabled;
99 private final Types types;
100 private final TransTypes transTypes;
101 private final boolean debugLower;
102 private final boolean disableProtectedAccessors; // experimental
103 private final PkgInfo pkginfoOpt;
104 private final boolean optimizeOuterThis;
105 private final boolean useMatchException;
106
107 protected Lower(Context context) {
108 context.put(lowerKey, this);
109 names = Names.instance(context);
110 log = Log.instance(context);
111 syms = Symtab.instance(context);
112 rs = Resolve.instance(context);
113 operators = Operators.instance(context);
114 chk = Check.instance(context);
115 attr = Attr.instance(context);
116 make = TreeMaker.instance(context);
117 cfolder = ConstFold.instance(context);
118 target = Target.instance(context);
119 typeEnvs = TypeEnvs.instance(context);
120 dollarAssertionsDisabled = names.
121 fromString(target.syntheticNameChar() + "assertionsDisabled");
122
123 types = Types.instance(context);
124 transTypes = TransTypes.instance(context);
125 Options options = Options.instance(context);
126 debugLower = options.isSet("debuglower");
127 pkginfoOpt = PkgInfo.get(options);
128 optimizeOuterThis =
129 target.optimizeOuterThis() ||
130 options.getBoolean("optimizeOuterThis", false);
131 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
132 Source source = Source.instance(context);
133 Preview preview = Preview.instance(context);
134 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
135 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
136 }
137
138 /** The currently enclosing class.
139 */
140 ClassSymbol currentClass;
141
142 /** A queue of all translated classes.
143 */
144 ListBuffer<JCTree> translated;
145
146 /** Environment for symbol lookup, set by translateTopLevelClass.
147 */
148 Env<AttrContext> attrEnv;
149
150 /** A hash table mapping syntax trees to their ending source positions.
151 */
152 EndPosTable endPosTable;
806
807 /** Look up a method in a given scope.
808 */
809 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
810 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
811 }
812
813 /** Anon inner classes are used as access constructor tags.
814 * accessConstructorTag will use an existing anon class if one is available,
815 * and synthesize a class (with makeEmptyClass) if one is not available.
816 * However, there is a small possibility that an existing class will not
817 * be generated as expected if it is inside a conditional with a constant
818 * expression. If that is found to be the case, create an empty class tree here.
819 */
820 private void checkAccessConstructorTags() {
821 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
822 ClassSymbol c = l.head;
823 if (isTranslatedClassAvailable(c))
824 continue;
825 // Create class definition tree.
826 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
827 c.outermostClass(), c.flatname, false);
828 swapAccessConstructorTag(c, cdec.sym);
829 translated.append(cdec);
830 }
831 }
832 // where
833 private boolean isTranslatedClassAvailable(ClassSymbol c) {
834 for (JCTree tree: translated) {
835 if (tree.hasTag(CLASSDEF)
836 && ((JCClassDecl) tree).sym == c) {
837 return true;
838 }
839 }
840 return false;
841 }
842
843 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
844 for (MethodSymbol methodSymbol : accessConstrs.values()) {
845 Assert.check(methodSymbol.type.hasTag(METHOD));
846 MethodType oldMethodType =
1043
1044 /** The qualifier to be used for accessing a symbol in an outer class.
1045 * This is either C.sym or C.this.sym, depending on whether or not
1046 * sym is static.
1047 * @param sym The accessed symbol.
1048 */
1049 JCExpression accessBase(DiagnosticPosition pos, Symbol sym) {
1050 return (sym.flags() & STATIC) != 0
1051 ? access(make.at(pos.getStartPosition()).QualIdent(sym.owner))
1052 : makeOwnerThis(pos, sym, true);
1053 }
1054
1055 /** Do we need an access method to reference private symbol?
1056 */
1057 boolean needsPrivateAccess(Symbol sym) {
1058 if (target.hasNestmateAccess()) {
1059 return false;
1060 }
1061 if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
1062 return false;
1063 } else if (sym.name == names.init && sym.owner.isDirectlyOrIndirectlyLocal()) {
1064 // private constructor in local class: relax protection
1065 sym.flags_field &= ~PRIVATE;
1066 return false;
1067 } else {
1068 return true;
1069 }
1070 }
1071
1072 /** Do we need an access method to reference symbol in other package?
1073 */
1074 boolean needsProtectedAccess(Symbol sym, JCTree tree) {
1075 if (disableProtectedAccessors) return false;
1076 if ((sym.flags() & PROTECTED) == 0 ||
1077 sym.owner.owner == currentClass.owner || // fast special case
1078 sym.packge() == currentClass.packge())
1079 return false;
1080 if (!currentClass.isSubClass(sym.owner, types))
1081 return true;
1082 if ((sym.flags() & STATIC) != 0 ||
1083 !tree.hasTag(SELECT) ||
1132 sym.owner.enclClass() != currentClass) {
1133 // A constant is replaced by its constant value.
1134 Object cv = ((VarSymbol)sym).getConstValue();
1135 if (cv != null) {
1136 make.at(tree.pos);
1137 return makeLit(sym.type, cv);
1138 }
1139 if (lambdaTranslationMap != null && lambdaTranslationMap.get(sym) != null) {
1140 return make.at(tree.pos).Ident(lambdaTranslationMap.get(sym));
1141 } else {
1142 // Otherwise replace the variable by its proxy.
1143 sym = proxies.get(sym);
1144 Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
1145 tree = make.at(tree.pos).Ident(sym);
1146 }
1147 }
1148 JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
1149 switch (sym.kind) {
1150 case TYP:
1151 if (sym.owner.kind != PCK) {
1152 // Convert type idents to
1153 // <flat name> or <package name> . <flat name>
1154 Name flatname = Convert.shortName(sym.flatName());
1155 while (base != null &&
1156 TreeInfo.symbol(base) != null &&
1157 TreeInfo.symbol(base).kind != PCK) {
1158 base = (base.hasTag(SELECT))
1159 ? ((JCFieldAccess) base).selected
1160 : null;
1161 }
1162 if (tree.hasTag(IDENT)) {
1163 ((JCIdent) tree).name = flatname;
1164 } else if (base == null) {
1165 tree = make.at(tree.pos).Ident(sym);
1166 ((JCIdent) tree).name = flatname;
1167 } else {
1168 ((JCFieldAccess) tree).selected = base;
1169 ((JCFieldAccess) tree).name = flatname;
1170 }
1171 }
1172 break;
1173 case MTH: case VAR:
1174 if (sym.owner.kind == TYP) {
1175
1176 // Access methods are required for
1177 // - private members,
1178 // - protected members in a superclass of an
1179 // enclosing class contained in another package.
1180 // - all non-private members accessed via a qualified super.
1181 boolean protAccess = refSuper && !needsPrivateAccess(sym)
1182 || needsProtectedAccess(sym, tree);
1183 boolean accReq = protAccess || needsPrivateAccess(sym);
1184
1185 // A base has to be supplied for
1186 // - simple identifiers accessing variables in outer classes.
1187 boolean baseReq =
1188 base == null &&
1189 sym.owner != syms.predefClass &&
1247 JCExpression access(JCExpression tree) {
1248 Symbol sym = TreeInfo.symbol(tree);
1249 return sym == null ? tree : access(sym, tree, null, false);
1250 }
1251
1252 /** Return access constructor for a private constructor,
1253 * or the constructor itself, if no access constructor is needed.
1254 * @param pos The position to report diagnostics, if any.
1255 * @param constr The private constructor.
1256 */
1257 Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) {
1258 if (needsPrivateAccess(constr)) {
1259 ClassSymbol accOwner = constr.owner.enclClass();
1260 MethodSymbol aconstr = accessConstrs.get(constr);
1261 if (aconstr == null) {
1262 List<Type> argtypes = constr.type.getParameterTypes();
1263 if ((accOwner.flags_field & ENUM) != 0)
1264 argtypes = argtypes
1265 .prepend(syms.intType)
1266 .prepend(syms.stringType);
1267 aconstr = new MethodSymbol(
1268 SYNTHETIC,
1269 names.init,
1270 new MethodType(
1271 argtypes.append(
1272 accessConstructorTag().erasure(types)),
1273 constr.type.getReturnType(),
1274 constr.type.getThrownTypes(),
1275 syms.methodClass),
1276 accOwner);
1277 enterSynthetic(pos, aconstr, accOwner.members());
1278 accessConstrs.put(constr, aconstr);
1279 accessed.append(constr);
1280 }
1281 return aconstr;
1282 } else {
1283 return constr;
1284 }
1285 }
1286
1287 /** Return an anonymous class nested in this toplevel class.
1288 */
1289 ClassSymbol accessConstructorTag() {
1290 ClassSymbol topClass = currentClass.outermostClass();
1291 ModuleSymbol topModle = topClass.packge().modle;
1292 for (int i = 1; ; i++) {
1293 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1294 target.syntheticNameChar() +
1295 i);
1296 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1297 if (ctag == null)
1298 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
1299 else if (!ctag.isAnonymous())
1300 continue;
1301 // keep a record of all tags, to verify that all are generated as required
1302 accessConstrTags = accessConstrTags.prepend(ctag);
1303 return ctag;
1304 }
1305 }
1306
1307 /** Add all required access methods for a private symbol to enclosing class.
1308 * @param sym The symbol.
1309 */
1310 void makeAccessible(Symbol sym) {
1311 JCClassDecl cdef = classDef(sym.owner.enclClass());
1312 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1313 if (sym.name == names.init) {
1314 cdef.defs = cdef.defs.prepend(
1315 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1316 } else {
1317 MethodSymbol[] accessors = accessSyms.get(sym);
1318 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1319 if (accessors[i] != null)
1320 cdef.defs = cdef.defs.prepend(
1321 accessDef(cdef.pos, sym, accessors[i], i));
1322 }
1323 }
1324 }
1325
1326 /** Construct definition of an access method.
1327 * @param pos The source code position of the definition.
1328 * @param vsym The private or protected symbol.
1329 * @param accessor The access method for the symbol.
1330 * @param acode The access code.
1331 */
1332 JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) {
1333 // System.err.println("access " + vsym + " with " + accessor);//DEBUG
1506 VarSymbol outerThis =
1507 new VarSymbol(flags | NOOUTERTHIS, outerThisName(target, owner), target, owner);
1508 outerThisStack = outerThisStack.prepend(outerThis);
1509 return outerThis;
1510 }
1511
1512 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1513 JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1514 vd.vartype = access(vd.vartype);
1515 return vd;
1516 }
1517
1518 /** Definition for this$n field.
1519 * @param pos The source code position of the definition.
1520 * @param owner The method in which the definition goes.
1521 */
1522 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1523 ClassSymbol c = owner.enclClass();
1524 boolean isMandated =
1525 // Anonymous constructors
1526 (owner.isConstructor() && owner.isAnonymous()) ||
1527 // Constructors of non-private inner member classes
1528 (owner.isConstructor() && c.isInner() &&
1529 !c.isPrivate() && !c.isStatic());
1530 long flags =
1531 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1532 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1533 owner.extraParams = owner.extraParams.prepend(outerThis);
1534 return makeOuterThisVarDecl(pos, outerThis);
1535 }
1536
1537 /** Definition for this$n field.
1538 * @param pos The source code position of the definition.
1539 * @param owner The class in which the definition goes.
1540 */
1541 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1542 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1543 return makeOuterThisVarDecl(pos, outerThis);
1544 }
1545
1546 /** Return a list of trees that load the free variables in given list,
1547 * in reverse order.
1548 * @param pos The source code position to be used for the trees.
1705 }
1706
1707 JCStatement exceptionalRethrow = make.Throw(make.Ident(primaryException));
1708 JCBlock exceptionalCloseBlock = make.Block(0L, List.of(exceptionalCloseStatement, exceptionalRethrow));
1709 JCCatch exceptionalCatchClause = make.Catch(primaryExceptionDecl, exceptionalCloseBlock);
1710
1711 //create the main try statement with the close:
1712 JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1713 List.of(exceptionalCatchClause),
1714 finallyClause);
1715
1716 outerTry.finallyCanCompleteNormally = true;
1717 stats.add(outerTry);
1718
1719 JCBlock newBlock = make.Block(0L, stats.toList());
1720 return newBlock;
1721 }
1722
1723 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1724 // convert to AutoCloseable if needed
1725 if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
1726 resource = convert(resource, syms.autoCloseableType);
1727 }
1728
1729 // create resource.close() method invocation
1730 JCExpression resourceClose = makeCall(resource,
1731 names.close,
1732 List.nil());
1733 return make.Exec(resourceClose);
1734 }
1735
1736 private JCExpression makeNonNullCheck(JCExpression expression) {
1737 return makeBinary(NE, expression, makeNull());
1738 }
1739
1740 /** Construct a tree that represents the outer instance
1741 * {@code C.this}. Never pick the current `this'.
1742 * @param pos The source code position to be used for the tree.
1743 * @param c The qualifier class.
1744 */
1745 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1857 }
1858
1859 /**************************************************************************
1860 * Code for .class
1861 *************************************************************************/
1862
1863 /** Return the symbol of a class to contain a cache of
1864 * compiler-generated statics such as class$ and the
1865 * $assertionsDisabled flag. We create an anonymous nested class
1866 * (unless one already exists) and return its symbol. However,
1867 * for backward compatibility in 1.4 and earlier we use the
1868 * top-level class itself.
1869 */
1870 private ClassSymbol outerCacheClass() {
1871 ClassSymbol clazz = outermostClassDef.sym;
1872 Scope s = clazz.members();
1873 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1874 if (sym.kind == TYP &&
1875 sym.name == names.empty &&
1876 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1877 return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
1878 }
1879
1880 /** Create an attributed tree of the form left.name(). */
1881 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1882 Assert.checkNonNull(left.type);
1883 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1884 TreeInfo.types(args));
1885 return make.App(make.Select(left, funcsym), args);
1886 }
1887
1888 /** The tree simulating a T.class expression.
1889 * @param clazz The tree identifying type T.
1890 */
1891 private JCExpression classOf(JCTree clazz) {
1892 return classOfType(clazz.type, clazz.pos());
1893 }
1894
1895 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1896 switch (type.getTag()) {
1897 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1909 VarSymbol sym = new VarSymbol(
1910 STATIC | PUBLIC | FINAL, names._class,
1911 syms.classType, type.tsym);
1912 return make_at(pos).Select(make.Type(type), sym);
1913 default:
1914 throw new AssertionError();
1915 }
1916 }
1917
1918 /**************************************************************************
1919 * Code for enabling/disabling assertions.
1920 *************************************************************************/
1921
1922 private ClassSymbol assertionsDisabledClassCache;
1923
1924 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1925 */
1926 private ClassSymbol assertionsDisabledClass() {
1927 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1928
1929 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
1930
1931 return assertionsDisabledClassCache;
1932 }
1933
1934 // This code is not particularly robust if the user has
1935 // previously declared a member named '$assertionsDisabled'.
1936 // The same faulty idiom also appears in the translation of
1937 // class literals above. We should report an error if a
1938 // previous declaration is not synthetic.
1939
1940 private JCExpression assertFlagTest(DiagnosticPosition pos) {
1941 // Outermost class may be either true class or an interface.
1942 ClassSymbol outermostClass = outermostClassDef.sym;
1943
1944 //only classes can hold a non-public field, look for a usable one:
1945 ClassSymbol container = !currentClass.isInterface() ? currentClass :
1946 assertionsDisabledClass();
1947
1948 VarSymbol assertDisabledSym =
1949 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2089 /** Visitor method: Translate a single node.
2090 * Attach the source position from the old tree to its replacement tree.
2091 */
2092 @Override
2093 public <T extends JCTree> T translate(T tree) {
2094 if (tree == null) {
2095 return null;
2096 } else {
2097 make_at(tree.pos());
2098 T result = super.translate(tree);
2099 if (endPosTable != null && result != tree) {
2100 endPosTable.replaceTree(tree, result);
2101 }
2102 return result;
2103 }
2104 }
2105
2106 /** Visitor method: Translate a single node, boxing or unboxing if needed.
2107 */
2108 public <T extends JCExpression> T translate(T tree, Type type) {
2109 return (tree == null) ? null : boxIfNeeded(translate(tree), type);
2110 }
2111
2112 /** Visitor method: Translate tree.
2113 */
2114 public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
2115 JCExpression prevEnclOp = this.enclOp;
2116 this.enclOp = enclOp;
2117 T res = translate(tree);
2118 this.enclOp = prevEnclOp;
2119 return res;
2120 }
2121
2122 /** Visitor method: Translate list of trees.
2123 */
2124 public <T extends JCExpression> List<T> translate(List<T> trees, Type type) {
2125 if (trees == null) return null;
2126 for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2127 l.head = translate(l.head, type);
2128 return trees;
2129 }
2228 encl.trans_local = encl.trans_local.prepend(currentClass);
2229 }
2230
2231 // Recursively translate members, taking into account that new members
2232 // might be created during the translation and prepended to the member
2233 // list `tree.defs'.
2234 List<JCTree> seen = List.nil();
2235 while (tree.defs != seen) {
2236 List<JCTree> unseen = tree.defs;
2237 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2238 JCTree outermostMemberDefPrev = outermostMemberDef;
2239 if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
2240 l.head = translate(l.head);
2241 outermostMemberDef = outermostMemberDefPrev;
2242 }
2243 seen = unseen;
2244 }
2245
2246 // Convert a protected modifier to public, mask static modifier.
2247 if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
2248 tree.mods.flags &= ClassFlags;
2249
2250 // Convert name to flat representation, replacing '.' by '$'.
2251 tree.name = Convert.shortName(currentClass.flatName());
2252
2253 // Add free variables proxy definitions to class.
2254
2255 for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2256 tree.defs = tree.defs.prepend(l.head);
2257 enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
2258 }
2259 // If this$n was accessed, add the field definition and
2260 // update initial constructors to initialize it
2261 if (currentClass.hasOuterInstance() && shouldEmitOuterThis(currentClass)) {
2262 tree.defs = tree.defs.prepend(otdef);
2263 enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2264
2265 for (JCTree def : tree.defs) {
2266 if (TreeInfo.isInitialConstructor(def)) {
2267 JCMethodDecl mdef = (JCMethodDecl) def;
2268 mdef.body.stats = mdef.body.stats.prepend(
2638
2639 MethodType indyType = msym.type.asMethodType();
2640 indyType = new MethodType(
2641 isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
2642 indyType.restype,
2643 indyType.thrown,
2644 syms.methodClass
2645 );
2646 DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName,
2647 syms.noSymbol,
2648 bsm.asHandle(),
2649 indyType,
2650 staticArgValues);
2651 JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), argName);
2652 qualifier.sym = dynSym;
2653 qualifier.type = msym.type.asMethodType().restype;
2654 return qualifier;
2655 }
2656
2657 public void visitMethodDef(JCMethodDecl tree) {
2658 if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
2659 // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2660 // argument list for each constructor of an enum.
2661 JCVariableDecl nameParam = make_at(tree.pos()).
2662 Param(names.fromString(target.syntheticNameChar() +
2663 "enum" + target.syntheticNameChar() + "name"),
2664 syms.stringType, tree.sym);
2665 nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
2666 JCVariableDecl ordParam = make.
2667 Param(names.fromString(target.syntheticNameChar() +
2668 "enum" + target.syntheticNameChar() +
2669 "ordinal"),
2670 syms.intType, tree.sym);
2671 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
2672
2673 MethodSymbol m = tree.sym;
2674 tree.params = tree.params.prepend(ordParam).prepend(nameParam);
2675
2676 m.extraParams = m.extraParams.prepend(ordParam.sym);
2677 m.extraParams = m.extraParams.prepend(nameParam.sym);
2679 m.erasure_field = new MethodType(
2680 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
2681 olderasure.getReturnType(),
2682 olderasure.getThrownTypes(),
2683 syms.methodClass);
2684 }
2685
2686 JCMethodDecl prevMethodDef = currentMethodDef;
2687 MethodSymbol prevMethodSym = currentMethodSym;
2688 try {
2689 currentMethodDef = tree;
2690 currentMethodSym = tree.sym;
2691 visitMethodDefInternal(tree);
2692 } finally {
2693 currentMethodDef = prevMethodDef;
2694 currentMethodSym = prevMethodSym;
2695 }
2696 }
2697
2698 private void visitMethodDefInternal(JCMethodDecl tree) {
2699 if (tree.name == names.init &&
2700 !currentClass.isStatic() &&
2701 (currentClass.isInner() || currentClass.isDirectlyOrIndirectlyLocal())) {
2702 // We are seeing a constructor of an inner class.
2703 MethodSymbol m = tree.sym;
2704
2705 // Push a new proxy scope for constructor parameters.
2706 // and create definitions for any this$n and proxy parameters.
2707 Map<Symbol, Symbol> prevProxies = proxies;
2708 proxies = new HashMap<>(proxies);
2709 List<VarSymbol> prevOuterThisStack = outerThisStack;
2710 List<VarSymbol> fvs = freevars(currentClass);
2711 JCVariableDecl otdef = null;
2712 if (currentClass.hasOuterInstance())
2713 otdef = outerThisDef(tree.pos, m);
2714 List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m, PARAMETER);
2715
2716 // Recursively translate result type, parameters and thrown list.
2717 tree.restype = translate(tree.restype);
2718 tree.params = translateVarDefs(tree.params);
2719 tree.thrown = translate(tree.thrown);
2760 // pop local variables from proxy stack
2761 proxies = prevProxies;
2762
2763 // recursively translate following local statements and
2764 // combine with this- or super-call
2765 List<JCStatement> stats = translate(tree.body.stats.tail);
2766 tree.body.stats = stats.prepend(selfCall).prependList(added);
2767 outerThisStack = prevOuterThisStack;
2768 } else {
2769 Map<Symbol, Symbol> prevLambdaTranslationMap =
2770 lambdaTranslationMap;
2771 try {
2772 lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 &&
2773 tree.sym.name.startsWith(names.lambda) ?
2774 makeTranslationMap(tree) : null;
2775 super.visitMethodDef(tree);
2776 } finally {
2777 lambdaTranslationMap = prevLambdaTranslationMap;
2778 }
2779 }
2780 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2781 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2782 // lets find out if there is any field waiting to be initialized
2783 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2784 for (Symbol sym : currentClass.getEnclosedElements()) {
2785 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2786 fields.append((VarSymbol) sym);
2787 }
2788 for (VarSymbol field: fields) {
2789 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2790 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2791 make.at(tree.pos);
2792 tree.body.stats = tree.body.stats.append(
2793 make.Exec(
2794 make.Assign(
2795 make.Select(make.This(field.owner.erasure(types)), field),
2796 make.Ident(param)).setType(field.erasure(types))));
2797 // we don't need the flag at the field anymore
2798 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2799 }
2800 }
3002 List.nil() : List.of(translate(tree.detail));
3003 if (!tree.cond.type.isFalse()) {
3004 cond = makeBinary
3005 (AND,
3006 cond,
3007 makeUnary(NOT, tree.cond));
3008 }
3009 result =
3010 make.If(cond,
3011 make_at(tree).
3012 Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
3013 null);
3014 } else {
3015 result = make.Skip();
3016 }
3017 }
3018
3019 public void visitApply(JCMethodInvocation tree) {
3020 Symbol meth = TreeInfo.symbol(tree.meth);
3021 List<Type> argtypes = meth.type.getParameterTypes();
3022 if (meth.name == names.init && meth.owner == syms.enumSym)
3023 argtypes = argtypes.tail.tail;
3024 tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
3025 tree.varargsElement = null;
3026 Name methName = TreeInfo.name(tree.meth);
3027 if (meth.name==names.init) {
3028 // We are seeing a this(...) or super(...) constructor call.
3029 // If an access constructor is used, append null as a last argument.
3030 Symbol constructor = accessConstructor(tree.pos(), meth);
3031 if (constructor != meth) {
3032 tree.args = tree.args.append(makeNull());
3033 TreeInfo.setSymbol(tree.meth, constructor);
3034 }
3035
3036 // If we are calling a constructor of a local class, add
3037 // free variables after explicit constructor arguments.
3038 ClassSymbol c = (ClassSymbol)constructor.owner;
3039 if (c.isDirectlyOrIndirectlyLocal() && !c.isStatic()) {
3040 tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
3041 }
3042
3043 // If we are calling a constructor of an enum class, pass
3044 // along the name and ordinal arguments
3045 if ((c.flags_field&ENUM) != 0 || c.getQualifiedName() == names.java_lang_Enum) {
3046 List<JCVariableDecl> params = currentMethodDef.params;
3047 if (currentMethodSym.owner.hasOuterInstance())
3109 while (args.nonEmpty()) {
3110 JCExpression arg = translate(args.head, varargsElement);
3111 elems.append(arg);
3112 args = args.tail;
3113 }
3114 JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
3115 List.nil(),
3116 elems.toList());
3117 boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
3118 result.append(boxedArgs);
3119 } else {
3120 if (args.length() != 1) throw new AssertionError(args);
3121 JCExpression arg = translate(args.head, parameter);
3122 anyChanges |= (arg != args.head);
3123 result.append(arg);
3124 if (!anyChanges) return _args;
3125 }
3126 return result.toList();
3127 }
3128
3129 /** Expand a boxing or unboxing conversion if needed. */
3130 @SuppressWarnings("unchecked") // XXX unchecked
3131 <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
3132 boolean havePrimitive = tree.type.isPrimitive();
3133 if (havePrimitive == type.isPrimitive())
3134 return tree;
3135 if (havePrimitive) {
3136 Type unboxedTarget = types.unboxedType(type);
3137 if (!unboxedTarget.hasTag(NONE)) {
3138 if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
3139 tree.type = unboxedTarget.constType(tree.type.constValue());
3140 return (T)boxPrimitive(tree, types.erasure(type));
3141 } else {
3142 tree = (T)boxPrimitive(tree);
3143 }
3144 } else {
3145 tree = (T)unbox(tree, type);
3146 }
3147 return tree;
3148 }
3512 * A statement of the form
3513 *
3514 * <pre>
3515 * for ( T v : coll ) stmt ;
3516 * </pre>
3517 *
3518 * (where coll implements {@code Iterable<? extends T>}) gets translated to
3519 *
3520 * <pre>{@code
3521 * for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
3522 * T v = (T) #i.next();
3523 * stmt;
3524 * }
3525 * }</pre>
3526 *
3527 * where #i is a freshly named synthetic local variable.
3528 */
3529 private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
3530 make_at(tree.expr.pos());
3531 Type iteratorTarget = syms.objectType;
3532 Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
3533 syms.iterableType.tsym);
3534 if (iterableType.getTypeArguments().nonEmpty())
3535 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
3536 tree.expr.type = types.erasure(types.skipTypeVars(tree.expr.type, false));
3537 tree.expr = transTypes.coerce(attrEnv, tree.expr, types.erasure(iterableType));
3538 Symbol iterator = lookupMethod(tree.expr.pos(),
3539 names.iterator,
3540 tree.expr.type,
3541 List.nil());
3542 Assert.check(types.isSameType(types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)), types.erasure(syms.iteratorType)));
3543 VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
3544 types.erasure(syms.iteratorType),
3545 currentMethodSym);
3546
3547 JCStatement init = make.
3548 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
3549 .setType(types.erasure(iterator.type))));
3550
3551 Symbol hasNext = lookupMethod(tree.expr.pos(),
3552 names.hasNext,
3553 itvar.type,
3554 List.nil());
3555 JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
3556 Symbol next = lookupMethod(tree.expr.pos(),
3557 names.next,
3558 itvar.type,
3559 List.nil());
3560 JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
3561
3562 Assert.check(tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE);
3605 new MethodSymbol(tree.flags | BLOCK,
3606 names.empty, null,
3607 currentClass);
3608 }
3609 super.visitBlock(tree);
3610 currentMethodSym = oldMethodSym;
3611 }
3612
3613 public void visitDoLoop(JCDoWhileLoop tree) {
3614 tree.body = translate(tree.body);
3615 tree.cond = translate(tree.cond, syms.booleanType);
3616 result = tree;
3617 }
3618
3619 public void visitWhileLoop(JCWhileLoop tree) {
3620 tree.cond = translate(tree.cond, syms.booleanType);
3621 tree.body = translate(tree.body);
3622 result = tree;
3623 }
3624
3625 public void visitForLoop(JCForLoop tree) {
3626 tree.init = translate(tree.init);
3627 if (tree.cond != null)
3628 tree.cond = translate(tree.cond, syms.booleanType);
3629 tree.step = translate(tree.step);
3630 tree.body = translate(tree.body);
3631 result = tree;
3632 }
3633
3634 public void visitReturn(JCReturn tree) {
3635 if (tree.expr != null)
3636 tree.expr = translate(tree.expr,
3637 types.erasure(currentMethodDef
3638 .restype.type));
3639 result = tree;
3640 }
3641
3642 public void visitSwitch(JCSwitch tree) {
3643 List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.patternSwitch,
3644 tree.wasEnumSelector,
4098 tree.value = translate(tree.value, tree.target.type);
4099 result = tree;
4100 }
4101
4102 public void visitNewArray(JCNewArray tree) {
4103 tree.elemtype = translate(tree.elemtype);
4104 for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
4105 if (t.head != null) t.head = translate(t.head, syms.intType);
4106 tree.elems = translate(tree.elems, types.elemtype(tree.type));
4107 result = tree;
4108 }
4109
4110 public void visitSelect(JCFieldAccess tree) {
4111 // need to special case-access of the form C.super.x
4112 // these will always need an access method, unless C
4113 // is a default interface subclassed by the current class.
4114 boolean qualifiedSuperAccess =
4115 tree.selected.hasTag(SELECT) &&
4116 TreeInfo.name(tree.selected) == names._super &&
4117 !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
4118 tree.selected = translate(tree.selected);
4119 if (tree.name == names._class) {
4120 result = classOf(tree.selected);
4121 }
4122 else if (tree.name == names._super &&
4123 types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
4124 //default super call!! Not a classic qualified super call
4125 TypeSymbol supSym = tree.selected.type.tsym;
4126 Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
4127 result = tree;
4128 }
4129 else if (tree.name == names._this || tree.name == names._super) {
4130 result = makeThis(tree.pos(), tree.selected.type.tsym);
4131 }
4132 else
4133 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
4134 }
4135
4136 public void visitLetExpr(LetExpr tree) {
4137 tree.defs = translate(tree.defs);
4138 tree.expr = translate(tree.expr, tree.type);
4139 result = tree;
4140 }
4141
4142 // There ought to be nothing to rewrite here;
4143 // we don't generate code.
4144 public void visitAnnotation(JCAnnotation tree) {
4145 result = tree;
4146 }
|
85
86 private final Names names;
87 private final Log log;
88 private final Symtab syms;
89 private final Resolve rs;
90 private final Operators operators;
91 private final Check chk;
92 private final Attr attr;
93 private TreeMaker make;
94 private DiagnosticPosition make_pos;
95 private final ConstFold cfolder;
96 private final Target target;
97 private final TypeEnvs typeEnvs;
98 private final Name dollarAssertionsDisabled;
99 private final Types types;
100 private final TransTypes transTypes;
101 private final boolean debugLower;
102 private final boolean disableProtectedAccessors; // experimental
103 private final PkgInfo pkginfoOpt;
104 private final boolean optimizeOuterThis;
105 private final boolean allowPrimitiveClasses;
106 private final boolean useMatchException;
107
108 protected Lower(Context context) {
109 context.put(lowerKey, this);
110 names = Names.instance(context);
111 log = Log.instance(context);
112 syms = Symtab.instance(context);
113 rs = Resolve.instance(context);
114 operators = Operators.instance(context);
115 chk = Check.instance(context);
116 attr = Attr.instance(context);
117 make = TreeMaker.instance(context);
118 cfolder = ConstFold.instance(context);
119 target = Target.instance(context);
120 typeEnvs = TypeEnvs.instance(context);
121 dollarAssertionsDisabled = names.
122 fromString(target.syntheticNameChar() + "assertionsDisabled");
123
124 types = Types.instance(context);
125 transTypes = TransTypes.instance(context);
126 Options options = Options.instance(context);
127 debugLower = options.isSet("debuglower");
128 pkginfoOpt = PkgInfo.get(options);
129 optimizeOuterThis =
130 target.optimizeOuterThis() ||
131 options.getBoolean("optimizeOuterThis", false);
132 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
133 Source source = Source.instance(context);
134 allowPrimitiveClasses = Source.Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
135 Preview preview = Preview.instance(context);
136 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
137 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
138 }
139
140 /** The currently enclosing class.
141 */
142 ClassSymbol currentClass;
143
144 /** A queue of all translated classes.
145 */
146 ListBuffer<JCTree> translated;
147
148 /** Environment for symbol lookup, set by translateTopLevelClass.
149 */
150 Env<AttrContext> attrEnv;
151
152 /** A hash table mapping syntax trees to their ending source positions.
153 */
154 EndPosTable endPosTable;
808
809 /** Look up a method in a given scope.
810 */
811 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
812 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
813 }
814
815 /** Anon inner classes are used as access constructor tags.
816 * accessConstructorTag will use an existing anon class if one is available,
817 * and synthesize a class (with makeEmptyClass) if one is not available.
818 * However, there is a small possibility that an existing class will not
819 * be generated as expected if it is inside a conditional with a constant
820 * expression. If that is found to be the case, create an empty class tree here.
821 */
822 private void checkAccessConstructorTags() {
823 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
824 ClassSymbol c = l.head;
825 if (isTranslatedClassAvailable(c))
826 continue;
827 // Create class definition tree.
828 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
829 c.outermostClass(), c.flatname, false);
830 swapAccessConstructorTag(c, cdec.sym);
831 translated.append(cdec);
832 }
833 }
834 // where
835 private boolean isTranslatedClassAvailable(ClassSymbol c) {
836 for (JCTree tree: translated) {
837 if (tree.hasTag(CLASSDEF)
838 && ((JCClassDecl) tree).sym == c) {
839 return true;
840 }
841 }
842 return false;
843 }
844
845 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
846 for (MethodSymbol methodSymbol : accessConstrs.values()) {
847 Assert.check(methodSymbol.type.hasTag(METHOD));
848 MethodType oldMethodType =
1045
1046 /** The qualifier to be used for accessing a symbol in an outer class.
1047 * This is either C.sym or C.this.sym, depending on whether or not
1048 * sym is static.
1049 * @param sym The accessed symbol.
1050 */
1051 JCExpression accessBase(DiagnosticPosition pos, Symbol sym) {
1052 return (sym.flags() & STATIC) != 0
1053 ? access(make.at(pos.getStartPosition()).QualIdent(sym.owner))
1054 : makeOwnerThis(pos, sym, true);
1055 }
1056
1057 /** Do we need an access method to reference private symbol?
1058 */
1059 boolean needsPrivateAccess(Symbol sym) {
1060 if (target.hasNestmateAccess()) {
1061 return false;
1062 }
1063 if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
1064 return false;
1065 } else if (names.isInitOrVNew(sym.name) && sym.owner.isDirectlyOrIndirectlyLocal()) {
1066 // private constructor in local class: relax protection
1067 sym.flags_field &= ~PRIVATE;
1068 return false;
1069 } else {
1070 return true;
1071 }
1072 }
1073
1074 /** Do we need an access method to reference symbol in other package?
1075 */
1076 boolean needsProtectedAccess(Symbol sym, JCTree tree) {
1077 if (disableProtectedAccessors) return false;
1078 if ((sym.flags() & PROTECTED) == 0 ||
1079 sym.owner.owner == currentClass.owner || // fast special case
1080 sym.packge() == currentClass.packge())
1081 return false;
1082 if (!currentClass.isSubClass(sym.owner, types))
1083 return true;
1084 if ((sym.flags() & STATIC) != 0 ||
1085 !tree.hasTag(SELECT) ||
1134 sym.owner.enclClass() != currentClass) {
1135 // A constant is replaced by its constant value.
1136 Object cv = ((VarSymbol)sym).getConstValue();
1137 if (cv != null) {
1138 make.at(tree.pos);
1139 return makeLit(sym.type, cv);
1140 }
1141 if (lambdaTranslationMap != null && lambdaTranslationMap.get(sym) != null) {
1142 return make.at(tree.pos).Ident(lambdaTranslationMap.get(sym));
1143 } else {
1144 // Otherwise replace the variable by its proxy.
1145 sym = proxies.get(sym);
1146 Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
1147 tree = make.at(tree.pos).Ident(sym);
1148 }
1149 }
1150 JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
1151 switch (sym.kind) {
1152 case TYP:
1153 if (sym.owner.kind != PCK) {
1154 // Make sure not to lose type fidelity due to symbol sharing between projections
1155 boolean requireReferenceProjection = allowPrimitiveClasses &&
1156 tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection();
1157 // Convert type idents to
1158 // <flat name> or <package name> . <flat name>
1159 Name flatname = Convert.shortName(sym.flatName());
1160 while (base != null &&
1161 TreeInfo.symbol(base) != null &&
1162 TreeInfo.symbol(base).kind != PCK) {
1163 base = (base.hasTag(SELECT))
1164 ? ((JCFieldAccess) base).selected
1165 : null;
1166 }
1167 if (tree.hasTag(IDENT)) {
1168 ((JCIdent) tree).name = flatname;
1169 } else if (base == null) {
1170 tree = make.at(tree.pos).Ident(sym);
1171 ((JCIdent) tree).name = flatname;
1172 if (requireReferenceProjection) {
1173 tree.setType(tree.type.referenceProjection());
1174 }
1175 } else {
1176 ((JCFieldAccess) tree).selected = base;
1177 ((JCFieldAccess) tree).name = flatname;
1178 if (requireReferenceProjection) {
1179 tree.setType(tree.type.referenceProjection());
1180 }
1181 }
1182 }
1183 break;
1184 case MTH: case VAR:
1185 if (sym.owner.kind == TYP) {
1186
1187 // Access methods are required for
1188 // - private members,
1189 // - protected members in a superclass of an
1190 // enclosing class contained in another package.
1191 // - all non-private members accessed via a qualified super.
1192 boolean protAccess = refSuper && !needsPrivateAccess(sym)
1193 || needsProtectedAccess(sym, tree);
1194 boolean accReq = protAccess || needsPrivateAccess(sym);
1195
1196 // A base has to be supplied for
1197 // - simple identifiers accessing variables in outer classes.
1198 boolean baseReq =
1199 base == null &&
1200 sym.owner != syms.predefClass &&
1258 JCExpression access(JCExpression tree) {
1259 Symbol sym = TreeInfo.symbol(tree);
1260 return sym == null ? tree : access(sym, tree, null, false);
1261 }
1262
1263 /** Return access constructor for a private constructor,
1264 * or the constructor itself, if no access constructor is needed.
1265 * @param pos The position to report diagnostics, if any.
1266 * @param constr The private constructor.
1267 */
1268 Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) {
1269 if (needsPrivateAccess(constr)) {
1270 ClassSymbol accOwner = constr.owner.enclClass();
1271 MethodSymbol aconstr = accessConstrs.get(constr);
1272 if (aconstr == null) {
1273 List<Type> argtypes = constr.type.getParameterTypes();
1274 if ((accOwner.flags_field & ENUM) != 0)
1275 argtypes = argtypes
1276 .prepend(syms.intType)
1277 .prepend(syms.stringType);
1278 Name constructorName = accOwner.isConcreteValueClass() ? names.vnew : names.init;
1279 aconstr = new MethodSymbol(
1280 SYNTHETIC,
1281 constructorName,
1282 new MethodType(
1283 argtypes.append(
1284 accessConstructorTag().erasure(types)),
1285 constr.type.getReturnType(),
1286 constr.type.getThrownTypes(),
1287 syms.methodClass),
1288 accOwner);
1289 enterSynthetic(pos, aconstr, accOwner.members());
1290 accessConstrs.put(constr, aconstr);
1291 accessed.append(constr);
1292 }
1293 return aconstr;
1294 } else {
1295 return constr;
1296 }
1297 }
1298
1299 /** Return an anonymous class nested in this toplevel class.
1300 */
1301 ClassSymbol accessConstructorTag() {
1302 ClassSymbol topClass = currentClass.outermostClass();
1303 ModuleSymbol topModle = topClass.packge().modle;
1304 for (int i = 1; ; i++) {
1305 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1306 target.syntheticNameChar() +
1307 i);
1308 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1309 if (ctag == null)
1310 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1311 else if (!ctag.isAnonymous())
1312 continue;
1313 // keep a record of all tags, to verify that all are generated as required
1314 accessConstrTags = accessConstrTags.prepend(ctag);
1315 return ctag;
1316 }
1317 }
1318
1319 /** Add all required access methods for a private symbol to enclosing class.
1320 * @param sym The symbol.
1321 */
1322 void makeAccessible(Symbol sym) {
1323 JCClassDecl cdef = classDef(sym.owner.enclClass());
1324 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1325 if (names.isInitOrVNew(sym.name)) {
1326 cdef.defs = cdef.defs.prepend(
1327 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1328 } else {
1329 MethodSymbol[] accessors = accessSyms.get(sym);
1330 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1331 if (accessors[i] != null)
1332 cdef.defs = cdef.defs.prepend(
1333 accessDef(cdef.pos, sym, accessors[i], i));
1334 }
1335 }
1336 }
1337
1338 /** Construct definition of an access method.
1339 * @param pos The source code position of the definition.
1340 * @param vsym The private or protected symbol.
1341 * @param accessor The access method for the symbol.
1342 * @param acode The access code.
1343 */
1344 JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) {
1345 // System.err.println("access " + vsym + " with " + accessor);//DEBUG
1518 VarSymbol outerThis =
1519 new VarSymbol(flags | NOOUTERTHIS, outerThisName(target, owner), target, owner);
1520 outerThisStack = outerThisStack.prepend(outerThis);
1521 return outerThis;
1522 }
1523
1524 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1525 JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1526 vd.vartype = access(vd.vartype);
1527 return vd;
1528 }
1529
1530 /** Definition for this$n field.
1531 * @param pos The source code position of the definition.
1532 * @param owner The method in which the definition goes.
1533 */
1534 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1535 ClassSymbol c = owner.enclClass();
1536 boolean isMandated =
1537 // Anonymous constructors
1538 (owner.isInitOrVNew() && owner.isAnonymous()) ||
1539 // Constructors of non-private inner member classes
1540 (owner.isInitOrVNew() && c.isInner() &&
1541 !c.isPrivate() && !c.isStatic());
1542 long flags =
1543 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1544 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1545 owner.extraParams = owner.extraParams.prepend(outerThis);
1546 return makeOuterThisVarDecl(pos, outerThis);
1547 }
1548
1549 /** Definition for this$n field.
1550 * @param pos The source code position of the definition.
1551 * @param owner The class in which the definition goes.
1552 */
1553 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1554 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1555 return makeOuterThisVarDecl(pos, outerThis);
1556 }
1557
1558 /** Return a list of trees that load the free variables in given list,
1559 * in reverse order.
1560 * @param pos The source code position to be used for the trees.
1717 }
1718
1719 JCStatement exceptionalRethrow = make.Throw(make.Ident(primaryException));
1720 JCBlock exceptionalCloseBlock = make.Block(0L, List.of(exceptionalCloseStatement, exceptionalRethrow));
1721 JCCatch exceptionalCatchClause = make.Catch(primaryExceptionDecl, exceptionalCloseBlock);
1722
1723 //create the main try statement with the close:
1724 JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1725 List.of(exceptionalCatchClause),
1726 finallyClause);
1727
1728 outerTry.finallyCanCompleteNormally = true;
1729 stats.add(outerTry);
1730
1731 JCBlock newBlock = make.Block(0L, stats.toList());
1732 return newBlock;
1733 }
1734
1735 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1736 // convert to AutoCloseable if needed
1737 if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) {
1738 resource = convert(resource, syms.autoCloseableType);
1739 }
1740
1741 // create resource.close() method invocation
1742 JCExpression resourceClose = makeCall(resource,
1743 names.close,
1744 List.nil());
1745 return make.Exec(resourceClose);
1746 }
1747
1748 private JCExpression makeNonNullCheck(JCExpression expression) {
1749 return makeBinary(NE, expression, makeNull());
1750 }
1751
1752 /** Construct a tree that represents the outer instance
1753 * {@code C.this}. Never pick the current `this'.
1754 * @param pos The source code position to be used for the tree.
1755 * @param c The qualifier class.
1756 */
1757 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1869 }
1870
1871 /**************************************************************************
1872 * Code for .class
1873 *************************************************************************/
1874
1875 /** Return the symbol of a class to contain a cache of
1876 * compiler-generated statics such as class$ and the
1877 * $assertionsDisabled flag. We create an anonymous nested class
1878 * (unless one already exists) and return its symbol. However,
1879 * for backward compatibility in 1.4 and earlier we use the
1880 * top-level class itself.
1881 */
1882 private ClassSymbol outerCacheClass() {
1883 ClassSymbol clazz = outermostClassDef.sym;
1884 Scope s = clazz.members();
1885 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1886 if (sym.kind == TYP &&
1887 sym.name == names.empty &&
1888 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1889 return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1890 }
1891
1892 /** Create an attributed tree of the form left.name(). */
1893 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1894 Assert.checkNonNull(left.type);
1895 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1896 TreeInfo.types(args));
1897 return make.App(make.Select(left, funcsym), args);
1898 }
1899
1900 /** The tree simulating a T.class expression.
1901 * @param clazz The tree identifying type T.
1902 */
1903 private JCExpression classOf(JCTree clazz) {
1904 return classOfType(clazz.type, clazz.pos());
1905 }
1906
1907 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1908 switch (type.getTag()) {
1909 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1921 VarSymbol sym = new VarSymbol(
1922 STATIC | PUBLIC | FINAL, names._class,
1923 syms.classType, type.tsym);
1924 return make_at(pos).Select(make.Type(type), sym);
1925 default:
1926 throw new AssertionError();
1927 }
1928 }
1929
1930 /**************************************************************************
1931 * Code for enabling/disabling assertions.
1932 *************************************************************************/
1933
1934 private ClassSymbol assertionsDisabledClassCache;
1935
1936 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1937 */
1938 private ClassSymbol assertionsDisabledClass() {
1939 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1940
1941 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1942
1943 return assertionsDisabledClassCache;
1944 }
1945
1946 // This code is not particularly robust if the user has
1947 // previously declared a member named '$assertionsDisabled'.
1948 // The same faulty idiom also appears in the translation of
1949 // class literals above. We should report an error if a
1950 // previous declaration is not synthetic.
1951
1952 private JCExpression assertFlagTest(DiagnosticPosition pos) {
1953 // Outermost class may be either true class or an interface.
1954 ClassSymbol outermostClass = outermostClassDef.sym;
1955
1956 //only classes can hold a non-public field, look for a usable one:
1957 ClassSymbol container = !currentClass.isInterface() ? currentClass :
1958 assertionsDisabledClass();
1959
1960 VarSymbol assertDisabledSym =
1961 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2101 /** Visitor method: Translate a single node.
2102 * Attach the source position from the old tree to its replacement tree.
2103 */
2104 @Override
2105 public <T extends JCTree> T translate(T tree) {
2106 if (tree == null) {
2107 return null;
2108 } else {
2109 make_at(tree.pos());
2110 T result = super.translate(tree);
2111 if (endPosTable != null && result != tree) {
2112 endPosTable.replaceTree(tree, result);
2113 }
2114 return result;
2115 }
2116 }
2117
2118 /** Visitor method: Translate a single node, boxing or unboxing if needed.
2119 */
2120 public <T extends JCExpression> T translate(T tree, Type type) {
2121 return (tree == null) ? null :
2122 applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
2123 }
2124
2125 /** Visitor method: Translate tree.
2126 */
2127 public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
2128 JCExpression prevEnclOp = this.enclOp;
2129 this.enclOp = enclOp;
2130 T res = translate(tree);
2131 this.enclOp = prevEnclOp;
2132 return res;
2133 }
2134
2135 /** Visitor method: Translate list of trees.
2136 */
2137 public <T extends JCExpression> List<T> translate(List<T> trees, Type type) {
2138 if (trees == null) return null;
2139 for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2140 l.head = translate(l.head, type);
2141 return trees;
2142 }
2241 encl.trans_local = encl.trans_local.prepend(currentClass);
2242 }
2243
2244 // Recursively translate members, taking into account that new members
2245 // might be created during the translation and prepended to the member
2246 // list `tree.defs'.
2247 List<JCTree> seen = List.nil();
2248 while (tree.defs != seen) {
2249 List<JCTree> unseen = tree.defs;
2250 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2251 JCTree outermostMemberDefPrev = outermostMemberDef;
2252 if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
2253 l.head = translate(l.head);
2254 outermostMemberDef = outermostMemberDefPrev;
2255 }
2256 seen = unseen;
2257 }
2258
2259 // Convert a protected modifier to public, mask static modifier.
2260 if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
2261 tree.mods.flags &= AdjustedClassFlags;
2262
2263 // Convert name to flat representation, replacing '.' by '$'.
2264 tree.name = Convert.shortName(currentClass.flatName());
2265
2266 // Add free variables proxy definitions to class.
2267
2268 for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2269 tree.defs = tree.defs.prepend(l.head);
2270 enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
2271 }
2272 // If this$n was accessed, add the field definition and
2273 // update initial constructors to initialize it
2274 if (currentClass.hasOuterInstance() && shouldEmitOuterThis(currentClass)) {
2275 tree.defs = tree.defs.prepend(otdef);
2276 enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2277
2278 for (JCTree def : tree.defs) {
2279 if (TreeInfo.isInitialConstructor(def)) {
2280 JCMethodDecl mdef = (JCMethodDecl) def;
2281 mdef.body.stats = mdef.body.stats.prepend(
2651
2652 MethodType indyType = msym.type.asMethodType();
2653 indyType = new MethodType(
2654 isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
2655 indyType.restype,
2656 indyType.thrown,
2657 syms.methodClass
2658 );
2659 DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName,
2660 syms.noSymbol,
2661 bsm.asHandle(),
2662 indyType,
2663 staticArgValues);
2664 JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), argName);
2665 qualifier.sym = dynSym;
2666 qualifier.type = msym.type.asMethodType().restype;
2667 return qualifier;
2668 }
2669
2670 public void visitMethodDef(JCMethodDecl tree) {
2671 // TODO - enum so is always <init>
2672 if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
2673 // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2674 // argument list for each constructor of an enum.
2675 JCVariableDecl nameParam = make_at(tree.pos()).
2676 Param(names.fromString(target.syntheticNameChar() +
2677 "enum" + target.syntheticNameChar() + "name"),
2678 syms.stringType, tree.sym);
2679 nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
2680 JCVariableDecl ordParam = make.
2681 Param(names.fromString(target.syntheticNameChar() +
2682 "enum" + target.syntheticNameChar() +
2683 "ordinal"),
2684 syms.intType, tree.sym);
2685 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
2686
2687 MethodSymbol m = tree.sym;
2688 tree.params = tree.params.prepend(ordParam).prepend(nameParam);
2689
2690 m.extraParams = m.extraParams.prepend(ordParam.sym);
2691 m.extraParams = m.extraParams.prepend(nameParam.sym);
2693 m.erasure_field = new MethodType(
2694 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
2695 olderasure.getReturnType(),
2696 olderasure.getThrownTypes(),
2697 syms.methodClass);
2698 }
2699
2700 JCMethodDecl prevMethodDef = currentMethodDef;
2701 MethodSymbol prevMethodSym = currentMethodSym;
2702 try {
2703 currentMethodDef = tree;
2704 currentMethodSym = tree.sym;
2705 visitMethodDefInternal(tree);
2706 } finally {
2707 currentMethodDef = prevMethodDef;
2708 currentMethodSym = prevMethodSym;
2709 }
2710 }
2711
2712 private void visitMethodDefInternal(JCMethodDecl tree) {
2713 if (names.isInitOrVNew(tree.name) &&
2714 !currentClass.isStatic() &&
2715 (currentClass.isInner() || currentClass.isDirectlyOrIndirectlyLocal())) {
2716 // We are seeing a constructor of an inner class.
2717 MethodSymbol m = tree.sym;
2718
2719 // Push a new proxy scope for constructor parameters.
2720 // and create definitions for any this$n and proxy parameters.
2721 Map<Symbol, Symbol> prevProxies = proxies;
2722 proxies = new HashMap<>(proxies);
2723 List<VarSymbol> prevOuterThisStack = outerThisStack;
2724 List<VarSymbol> fvs = freevars(currentClass);
2725 JCVariableDecl otdef = null;
2726 if (currentClass.hasOuterInstance())
2727 otdef = outerThisDef(tree.pos, m);
2728 List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m, PARAMETER);
2729
2730 // Recursively translate result type, parameters and thrown list.
2731 tree.restype = translate(tree.restype);
2732 tree.params = translateVarDefs(tree.params);
2733 tree.thrown = translate(tree.thrown);
2774 // pop local variables from proxy stack
2775 proxies = prevProxies;
2776
2777 // recursively translate following local statements and
2778 // combine with this- or super-call
2779 List<JCStatement> stats = translate(tree.body.stats.tail);
2780 tree.body.stats = stats.prepend(selfCall).prependList(added);
2781 outerThisStack = prevOuterThisStack;
2782 } else {
2783 Map<Symbol, Symbol> prevLambdaTranslationMap =
2784 lambdaTranslationMap;
2785 try {
2786 lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 &&
2787 tree.sym.name.startsWith(names.lambda) ?
2788 makeTranslationMap(tree) : null;
2789 super.visitMethodDef(tree);
2790 } finally {
2791 lambdaTranslationMap = prevLambdaTranslationMap;
2792 }
2793 }
2794 if (names.isInitOrVNew(tree.name) && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2795 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2796 // lets find out if there is any field waiting to be initialized
2797 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2798 for (Symbol sym : currentClass.getEnclosedElements()) {
2799 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2800 fields.append((VarSymbol) sym);
2801 }
2802 for (VarSymbol field: fields) {
2803 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2804 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2805 make.at(tree.pos);
2806 tree.body.stats = tree.body.stats.append(
2807 make.Exec(
2808 make.Assign(
2809 make.Select(make.This(field.owner.erasure(types)), field),
2810 make.Ident(param)).setType(field.erasure(types))));
2811 // we don't need the flag at the field anymore
2812 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2813 }
2814 }
3016 List.nil() : List.of(translate(tree.detail));
3017 if (!tree.cond.type.isFalse()) {
3018 cond = makeBinary
3019 (AND,
3020 cond,
3021 makeUnary(NOT, tree.cond));
3022 }
3023 result =
3024 make.If(cond,
3025 make_at(tree).
3026 Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
3027 null);
3028 } else {
3029 result = make.Skip();
3030 }
3031 }
3032
3033 public void visitApply(JCMethodInvocation tree) {
3034 Symbol meth = TreeInfo.symbol(tree.meth);
3035 List<Type> argtypes = meth.type.getParameterTypes();
3036 // TODO - is enum so always <init>.
3037 if (names.isInitOrVNew(meth.name) && meth.owner == syms.enumSym)
3038 argtypes = argtypes.tail.tail;
3039 tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
3040 tree.varargsElement = null;
3041 Name methName = TreeInfo.name(tree.meth);
3042 if (names.isInitOrVNew(meth.name)) {
3043 // We are seeing a this(...) or super(...) constructor call.
3044 // If an access constructor is used, append null as a last argument.
3045 Symbol constructor = accessConstructor(tree.pos(), meth);
3046 if (constructor != meth) {
3047 tree.args = tree.args.append(makeNull());
3048 TreeInfo.setSymbol(tree.meth, constructor);
3049 }
3050
3051 // If we are calling a constructor of a local class, add
3052 // free variables after explicit constructor arguments.
3053 ClassSymbol c = (ClassSymbol)constructor.owner;
3054 if (c.isDirectlyOrIndirectlyLocal() && !c.isStatic()) {
3055 tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
3056 }
3057
3058 // If we are calling a constructor of an enum class, pass
3059 // along the name and ordinal arguments
3060 if ((c.flags_field&ENUM) != 0 || c.getQualifiedName() == names.java_lang_Enum) {
3061 List<JCVariableDecl> params = currentMethodDef.params;
3062 if (currentMethodSym.owner.hasOuterInstance())
3124 while (args.nonEmpty()) {
3125 JCExpression arg = translate(args.head, varargsElement);
3126 elems.append(arg);
3127 args = args.tail;
3128 }
3129 JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
3130 List.nil(),
3131 elems.toList());
3132 boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
3133 result.append(boxedArgs);
3134 } else {
3135 if (args.length() != 1) throw new AssertionError(args);
3136 JCExpression arg = translate(args.head, parameter);
3137 anyChanges |= (arg != args.head);
3138 result.append(arg);
3139 if (!anyChanges) return _args;
3140 }
3141 return result.toList();
3142 }
3143
3144 /** Apply primitive value/reference conversions as needed */
3145 @SuppressWarnings("unchecked")
3146 <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
3147 boolean haveValue = tree.type.isPrimitiveClass();
3148 if (haveValue == type.isPrimitiveClass())
3149 return tree;
3150 // For narrowing conversion, insert a cast which should trigger a null check
3151 // For widening conversions, insert a cast if emitting a unified class file.
3152 return (T) make.TypeCast(type, tree);
3153 }
3154
3155 /** Expand a boxing or unboxing conversion if needed. */
3156 @SuppressWarnings("unchecked") // XXX unchecked
3157 <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
3158 boolean havePrimitive = tree.type.isPrimitive();
3159 if (havePrimitive == type.isPrimitive())
3160 return tree;
3161 if (havePrimitive) {
3162 Type unboxedTarget = types.unboxedType(type);
3163 if (!unboxedTarget.hasTag(NONE)) {
3164 if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
3165 tree.type = unboxedTarget.constType(tree.type.constValue());
3166 return (T)boxPrimitive(tree, types.erasure(type));
3167 } else {
3168 tree = (T)boxPrimitive(tree);
3169 }
3170 } else {
3171 tree = (T)unbox(tree, type);
3172 }
3173 return tree;
3174 }
3538 * A statement of the form
3539 *
3540 * <pre>
3541 * for ( T v : coll ) stmt ;
3542 * </pre>
3543 *
3544 * (where coll implements {@code Iterable<? extends T>}) gets translated to
3545 *
3546 * <pre>{@code
3547 * for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
3548 * T v = (T) #i.next();
3549 * stmt;
3550 * }
3551 * }</pre>
3552 *
3553 * where #i is a freshly named synthetic local variable.
3554 */
3555 private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
3556 make_at(tree.expr.pos());
3557 Type iteratorTarget = syms.objectType;
3558 Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()),
3559 syms.iterableType.tsym);
3560 if (iterableType.getTypeArguments().nonEmpty())
3561 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
3562 tree.expr.type = types.erasure(types.skipTypeVars(tree.expr.type, false));
3563 tree.expr = transTypes.coerce(attrEnv, tree.expr, types.erasure(iterableType));
3564 Symbol iterator = lookupMethod(tree.expr.pos(),
3565 names.iterator,
3566 tree.expr.type,
3567 List.nil());
3568 Assert.check(types.isSameType(types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)), types.erasure(syms.iteratorType)));
3569 VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
3570 types.erasure(syms.iteratorType),
3571 currentMethodSym);
3572
3573 JCStatement init = make.
3574 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
3575 .setType(types.erasure(iterator.type))));
3576
3577 Symbol hasNext = lookupMethod(tree.expr.pos(),
3578 names.hasNext,
3579 itvar.type,
3580 List.nil());
3581 JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
3582 Symbol next = lookupMethod(tree.expr.pos(),
3583 names.next,
3584 itvar.type,
3585 List.nil());
3586 JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
3587
3588 Assert.check(tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE);
3631 new MethodSymbol(tree.flags | BLOCK,
3632 names.empty, null,
3633 currentClass);
3634 }
3635 super.visitBlock(tree);
3636 currentMethodSym = oldMethodSym;
3637 }
3638
3639 public void visitDoLoop(JCDoWhileLoop tree) {
3640 tree.body = translate(tree.body);
3641 tree.cond = translate(tree.cond, syms.booleanType);
3642 result = tree;
3643 }
3644
3645 public void visitWhileLoop(JCWhileLoop tree) {
3646 tree.cond = translate(tree.cond, syms.booleanType);
3647 tree.body = translate(tree.body);
3648 result = tree;
3649 }
3650
3651 public void visitWithField(JCWithField tree) {
3652 Type fieldType = tree.field.type;
3653 tree.field = translate(tree.field, tree);
3654 tree.value = translate(tree.value, fieldType); // important to use pre-translation type.
3655
3656 // If translated field is an Apply, we are
3657 // seeing an access method invocation. In this case, append
3658 // right hand side as last argument of the access method.
3659 if (tree.field.hasTag(APPLY)) {
3660 JCMethodInvocation app = (JCMethodInvocation) tree.field;
3661 app.args = List.of(tree.value).prependList(app.args);
3662 result = app;
3663 } else {
3664 result = tree;
3665 }
3666 }
3667
3668 public void visitForLoop(JCForLoop tree) {
3669 tree.init = translate(tree.init);
3670 if (tree.cond != null)
3671 tree.cond = translate(tree.cond, syms.booleanType);
3672 tree.step = translate(tree.step);
3673 tree.body = translate(tree.body);
3674 result = tree;
3675 }
3676
3677 public void visitReturn(JCReturn tree) {
3678 if (tree.expr != null)
3679 tree.expr = translate(tree.expr,
3680 types.erasure(currentMethodDef
3681 .restype.type));
3682 result = tree;
3683 }
3684
3685 public void visitSwitch(JCSwitch tree) {
3686 List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.patternSwitch,
3687 tree.wasEnumSelector,
4141 tree.value = translate(tree.value, tree.target.type);
4142 result = tree;
4143 }
4144
4145 public void visitNewArray(JCNewArray tree) {
4146 tree.elemtype = translate(tree.elemtype);
4147 for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
4148 if (t.head != null) t.head = translate(t.head, syms.intType);
4149 tree.elems = translate(tree.elems, types.elemtype(tree.type));
4150 result = tree;
4151 }
4152
4153 public void visitSelect(JCFieldAccess tree) {
4154 // need to special case-access of the form C.super.x
4155 // these will always need an access method, unless C
4156 // is a default interface subclassed by the current class.
4157 boolean qualifiedSuperAccess =
4158 tree.selected.hasTag(SELECT) &&
4159 TreeInfo.name(tree.selected) == names._super &&
4160 !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
4161 /* JDK-8269956: Where a reflective (class) literal is needed, the unqualified Point.class is
4162 * always the "primary" mirror - representing the primitive reference runtime type - thereby
4163 * always matching the behavior of Object::getClass
4164 */
4165 boolean needPrimaryMirror = tree.name == names._class && tree.selected.type.isReferenceProjection();
4166 tree.selected = translate(tree.selected);
4167 if (needPrimaryMirror && allowPrimitiveClasses && tree.selected.type.isPrimitiveClass()) {
4168 tree.selected.setType(tree.selected.type.referenceProjection());
4169 }
4170 if (tree.name == names._class) {
4171 result = classOf(tree.selected);
4172 }
4173 else if (tree.name == names._super &&
4174 types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
4175 //default super call!! Not a classic qualified super call
4176 TypeSymbol supSym = tree.selected.type.tsym;
4177 Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym));
4178 result = tree;
4179 }
4180 else if (tree.name == names._this || tree.name == names._super) {
4181 result = makeThis(tree.pos(), tree.selected.type.tsym);
4182 }
4183 else
4184 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
4185 }
4186
4187 public void visitLetExpr(LetExpr tree) {
4188 tree.defs = translate(tree.defs);
4189 tree.expr = translate(tree.expr, tree.type);
4190 result = tree;
4191 }
4192
4193 // There ought to be nothing to rewrite here;
4194 // we don't generate code.
4195 public void visitAnnotation(JCAnnotation tree) {
4196 result = tree;
4197 }
|