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 @SuppressWarnings("this-escape")
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 Preview preview = Preview.instance(context);
135 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
136 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
137 }
138
139 /** The currently enclosing class.
140 */
141 ClassSymbol currentClass;
142
143 /** A queue of all translated classes.
144 */
145 ListBuffer<JCTree> translated;
146
147 /** Environment for symbol lookup, set by translateTopLevelClass.
148 */
149 Env<AttrContext> attrEnv;
150
151 /** A hash table mapping syntax trees to their ending source positions.
152 */
153 EndPosTable endPosTable;
890
891 /** Look up a method in a given scope.
892 */
893 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
894 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
895 }
896
897 /** Anon inner classes are used as access constructor tags.
898 * accessConstructorTag will use an existing anon class if one is available,
899 * and synthesize a class (with makeEmptyClass) if one is not available.
900 * However, there is a small possibility that an existing class will not
901 * be generated as expected if it is inside a conditional with a constant
902 * expression. If that is found to be the case, create an empty class tree here.
903 */
904 private void checkAccessConstructorTags() {
905 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
906 ClassSymbol c = l.head;
907 if (isTranslatedClassAvailable(c))
908 continue;
909 // Create class definition tree.
910 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
911 c.outermostClass(), c.flatname, false);
912 swapAccessConstructorTag(c, cdec.sym);
913 translated.append(cdec);
914 }
915 }
916 // where
917 private boolean isTranslatedClassAvailable(ClassSymbol c) {
918 for (JCTree tree: translated) {
919 if (tree.hasTag(CLASSDEF)
920 && ((JCClassDecl) tree).sym == c) {
921 return true;
922 }
923 }
924 return false;
925 }
926
927 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
928 for (MethodSymbol methodSymbol : accessConstrs.values()) {
929 Assert.check(methodSymbol.type.hasTag(METHOD));
930 MethodType oldMethodType =
1127
1128 /** The qualifier to be used for accessing a symbol in an outer class.
1129 * This is either C.sym or C.this.sym, depending on whether or not
1130 * sym is static.
1131 * @param sym The accessed symbol.
1132 */
1133 JCExpression accessBase(DiagnosticPosition pos, Symbol sym) {
1134 return (sym.flags() & STATIC) != 0
1135 ? access(make.at(pos.getStartPosition()).QualIdent(sym.owner))
1136 : makeOwnerThis(pos, sym, true);
1137 }
1138
1139 /** Do we need an access method to reference private symbol?
1140 */
1141 boolean needsPrivateAccess(Symbol sym) {
1142 if (target.hasNestmateAccess()) {
1143 return false;
1144 }
1145 if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
1146 return false;
1147 } else if (sym.name == names.init && sym.owner.isDirectlyOrIndirectlyLocal()) {
1148 // private constructor in local class: relax protection
1149 sym.flags_field &= ~PRIVATE;
1150 return false;
1151 } else {
1152 return true;
1153 }
1154 }
1155
1156 /** Do we need an access method to reference symbol in other package?
1157 */
1158 boolean needsProtectedAccess(Symbol sym, JCTree tree) {
1159 if (disableProtectedAccessors) return false;
1160 if ((sym.flags() & PROTECTED) == 0 ||
1161 sym.owner.owner == currentClass.owner || // fast special case
1162 sym.packge() == currentClass.packge())
1163 return false;
1164 if (!currentClass.isSubClass(sym.owner, types))
1165 return true;
1166 if ((sym.flags() & STATIC) != 0 ||
1167 !tree.hasTag(SELECT) ||
1216 sym.owner.enclClass() != currentClass) {
1217 // A constant is replaced by its constant value.
1218 Object cv = ((VarSymbol)sym).getConstValue();
1219 if (cv != null) {
1220 make.at(tree.pos);
1221 return makeLit(sym.type, cv);
1222 }
1223 if (lambdaTranslationMap != null && lambdaTranslationMap.get(sym) != null) {
1224 return make.at(tree.pos).Ident(lambdaTranslationMap.get(sym));
1225 } else {
1226 // Otherwise replace the variable by its proxy.
1227 sym = proxies.get(sym);
1228 Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
1229 tree = make.at(tree.pos).Ident(sym);
1230 }
1231 }
1232 JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
1233 switch (sym.kind) {
1234 case TYP:
1235 if (sym.owner.kind != PCK) {
1236 // Convert type idents to
1237 // <flat name> or <package name> . <flat name>
1238 Name flatname = Convert.shortName(sym.flatName());
1239 while (base != null &&
1240 TreeInfo.symbol(base) != null &&
1241 TreeInfo.symbol(base).kind != PCK) {
1242 base = (base.hasTag(SELECT))
1243 ? ((JCFieldAccess) base).selected
1244 : null;
1245 }
1246 if (tree.hasTag(IDENT)) {
1247 ((JCIdent) tree).name = flatname;
1248 } else if (base == null) {
1249 tree = make.at(tree.pos).Ident(sym);
1250 ((JCIdent) tree).name = flatname;
1251 } else {
1252 ((JCFieldAccess) tree).selected = base;
1253 ((JCFieldAccess) tree).name = flatname;
1254 }
1255 }
1256 break;
1257 case MTH: case VAR:
1258 if (sym.owner.kind == TYP) {
1259
1260 // Access methods are required for
1261 // - private members,
1262 // - protected members in a superclass of an
1263 // enclosing class contained in another package.
1264 // - all non-private members accessed via a qualified super.
1265 boolean protAccess = refSuper && !needsPrivateAccess(sym)
1266 || needsProtectedAccess(sym, tree);
1267 boolean accReq = protAccess || needsPrivateAccess(sym);
1268
1269 // A base has to be supplied for
1270 // - simple identifiers accessing variables in outer classes.
1271 boolean baseReq =
1272 base == null &&
1273 sym.owner != syms.predefClass &&
1331 JCExpression access(JCExpression tree) {
1332 Symbol sym = TreeInfo.symbol(tree);
1333 return sym == null ? tree : access(sym, tree, null, false);
1334 }
1335
1336 /** Return access constructor for a private constructor,
1337 * or the constructor itself, if no access constructor is needed.
1338 * @param pos The position to report diagnostics, if any.
1339 * @param constr The private constructor.
1340 */
1341 Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) {
1342 if (needsPrivateAccess(constr)) {
1343 ClassSymbol accOwner = constr.owner.enclClass();
1344 MethodSymbol aconstr = accessConstrs.get(constr);
1345 if (aconstr == null) {
1346 List<Type> argtypes = constr.type.getParameterTypes();
1347 if ((accOwner.flags_field & ENUM) != 0)
1348 argtypes = argtypes
1349 .prepend(syms.intType)
1350 .prepend(syms.stringType);
1351 aconstr = new MethodSymbol(
1352 SYNTHETIC,
1353 names.init,
1354 new MethodType(
1355 argtypes.append(
1356 accessConstructorTag().erasure(types)),
1357 constr.type.getReturnType(),
1358 constr.type.getThrownTypes(),
1359 syms.methodClass),
1360 accOwner);
1361 enterSynthetic(pos, aconstr, accOwner.members());
1362 accessConstrs.put(constr, aconstr);
1363 accessed.append(constr);
1364 }
1365 return aconstr;
1366 } else {
1367 return constr;
1368 }
1369 }
1370
1371 /** Return an anonymous class nested in this toplevel class.
1372 */
1373 ClassSymbol accessConstructorTag() {
1374 ClassSymbol topClass = currentClass.outermostClass();
1375 ModuleSymbol topModle = topClass.packge().modle;
1376 for (int i = 1; ; i++) {
1377 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1378 target.syntheticNameChar() +
1379 i);
1380 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1381 if (ctag == null)
1382 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
1383 else if (!ctag.isAnonymous())
1384 continue;
1385 // keep a record of all tags, to verify that all are generated as required
1386 accessConstrTags = accessConstrTags.prepend(ctag);
1387 return ctag;
1388 }
1389 }
1390
1391 /** Add all required access methods for a private symbol to enclosing class.
1392 * @param sym The symbol.
1393 */
1394 void makeAccessible(Symbol sym) {
1395 JCClassDecl cdef = classDef(sym.owner.enclClass());
1396 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1397 if (sym.name == names.init) {
1398 cdef.defs = cdef.defs.prepend(
1399 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1400 } else {
1401 MethodSymbol[] accessors = accessSyms.get(sym);
1402 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1403 if (accessors[i] != null)
1404 cdef.defs = cdef.defs.prepend(
1405 accessDef(cdef.pos, sym, accessors[i], i));
1406 }
1407 }
1408 }
1409
1410 /** Construct definition of an access method.
1411 * @param pos The source code position of the definition.
1412 * @param vsym The private or protected symbol.
1413 * @param accessor The access method for the symbol.
1414 * @param acode The access code.
1415 */
1416 JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) {
1417 // System.err.println("access " + vsym + " with " + accessor);//DEBUG
1590 VarSymbol outerThis =
1591 new VarSymbol(flags | NOOUTERTHIS, outerThisName(target, owner), target, owner);
1592 outerThisStack = outerThisStack.prepend(outerThis);
1593 return outerThis;
1594 }
1595
1596 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1597 JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1598 vd.vartype = access(vd.vartype);
1599 return vd;
1600 }
1601
1602 /** Definition for this$n field.
1603 * @param pos The source code position of the definition.
1604 * @param owner The method in which the definition goes.
1605 */
1606 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1607 ClassSymbol c = owner.enclClass();
1608 boolean isMandated =
1609 // Anonymous constructors
1610 (owner.isConstructor() && owner.isAnonymous()) ||
1611 // Constructors of non-private inner member classes
1612 (owner.isConstructor() && c.isInner() &&
1613 !c.isPrivate() && !c.isStatic());
1614 long flags =
1615 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1616 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1617 owner.extraParams = owner.extraParams.prepend(outerThis);
1618 return makeOuterThisVarDecl(pos, outerThis);
1619 }
1620
1621 /** Definition for this$n field.
1622 * @param pos The source code position of the definition.
1623 * @param owner The class in which the definition goes.
1624 */
1625 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1626 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1627 return makeOuterThisVarDecl(pos, outerThis);
1628 }
1629
1630 /** Return a list of trees that load the free variables in given list,
1631 * in reverse order.
1632 * @param pos The source code position to be used for the trees.
1789 }
1790
1791 JCStatement exceptionalRethrow = make.Throw(make.Ident(primaryException));
1792 JCBlock exceptionalCloseBlock = make.Block(0L, List.of(exceptionalCloseStatement, exceptionalRethrow));
1793 JCCatch exceptionalCatchClause = make.Catch(primaryExceptionDecl, exceptionalCloseBlock);
1794
1795 //create the main try statement with the close:
1796 JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1797 List.of(exceptionalCatchClause),
1798 finallyClause);
1799
1800 outerTry.finallyCanCompleteNormally = true;
1801 stats.add(outerTry);
1802
1803 JCBlock newBlock = make.Block(0L, stats.toList());
1804 return newBlock;
1805 }
1806
1807 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1808 // convert to AutoCloseable if needed
1809 if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
1810 resource = convert(resource, syms.autoCloseableType);
1811 }
1812
1813 // create resource.close() method invocation
1814 JCExpression resourceClose = makeCall(resource,
1815 names.close,
1816 List.nil());
1817 return make.Exec(resourceClose);
1818 }
1819
1820 private JCExpression makeNonNullCheck(JCExpression expression) {
1821 return makeBinary(NE, expression, makeNull());
1822 }
1823
1824 /** Construct a tree that represents the outer instance
1825 * {@code C.this}. Never pick the current `this'.
1826 * @param pos The source code position to be used for the tree.
1827 * @param c The qualifier class.
1828 */
1829 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1941 }
1942
1943 /**************************************************************************
1944 * Code for .class
1945 *************************************************************************/
1946
1947 /** Return the symbol of a class to contain a cache of
1948 * compiler-generated statics such as class$ and the
1949 * $assertionsDisabled flag. We create an anonymous nested class
1950 * (unless one already exists) and return its symbol. However,
1951 * for backward compatibility in 1.4 and earlier we use the
1952 * top-level class itself.
1953 */
1954 private ClassSymbol outerCacheClass() {
1955 ClassSymbol clazz = outermostClassDef.sym;
1956 Scope s = clazz.members();
1957 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1958 if (sym.kind == TYP &&
1959 sym.name == names.empty &&
1960 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1961 return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
1962 }
1963
1964 /** Create an attributed tree of the form left.name(). */
1965 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1966 Assert.checkNonNull(left.type);
1967 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1968 TreeInfo.types(args));
1969 return make.App(make.Select(left, funcsym), args);
1970 }
1971
1972 /** The tree simulating a T.class expression.
1973 * @param clazz The tree identifying type T.
1974 */
1975 private JCExpression classOf(JCTree clazz) {
1976 return classOfType(clazz.type, clazz.pos());
1977 }
1978
1979 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1980 switch (type.getTag()) {
1981 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1993 VarSymbol sym = new VarSymbol(
1994 STATIC | PUBLIC | FINAL, names._class,
1995 syms.classType, type.tsym);
1996 return make_at(pos).Select(make.Type(type), sym);
1997 default:
1998 throw new AssertionError();
1999 }
2000 }
2001
2002 /**************************************************************************
2003 * Code for enabling/disabling assertions.
2004 *************************************************************************/
2005
2006 private ClassSymbol assertionsDisabledClassCache;
2007
2008 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
2009 */
2010 private ClassSymbol assertionsDisabledClass() {
2011 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
2012
2013 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
2014
2015 return assertionsDisabledClassCache;
2016 }
2017
2018 // This code is not particularly robust if the user has
2019 // previously declared a member named '$assertionsDisabled'.
2020 // The same faulty idiom also appears in the translation of
2021 // class literals above. We should report an error if a
2022 // previous declaration is not synthetic.
2023
2024 private JCExpression assertFlagTest(DiagnosticPosition pos) {
2025 // Outermost class may be either true class or an interface.
2026 ClassSymbol outermostClass = outermostClassDef.sym;
2027
2028 //only classes can hold a non-public field, look for a usable one:
2029 ClassSymbol container = !currentClass.isInterface() ? currentClass :
2030 assertionsDisabledClass();
2031
2032 VarSymbol assertDisabledSym =
2033 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2173 /** Visitor method: Translate a single node.
2174 * Attach the source position from the old tree to its replacement tree.
2175 */
2176 @Override
2177 public <T extends JCTree> T translate(T tree) {
2178 if (tree == null) {
2179 return null;
2180 } else {
2181 make_at(tree.pos());
2182 T result = super.translate(tree);
2183 if (endPosTable != null && result != tree) {
2184 endPosTable.replaceTree(tree, result);
2185 }
2186 return result;
2187 }
2188 }
2189
2190 /** Visitor method: Translate a single node, boxing or unboxing if needed.
2191 */
2192 public <T extends JCExpression> T translate(T tree, Type type) {
2193 return (tree == null) ? null : boxIfNeeded(translate(tree), type);
2194 }
2195
2196 /** Visitor method: Translate tree.
2197 */
2198 public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
2199 JCExpression prevEnclOp = this.enclOp;
2200 this.enclOp = enclOp;
2201 T res = translate(tree);
2202 this.enclOp = prevEnclOp;
2203 return res;
2204 }
2205
2206 /** Visitor method: Translate list of trees.
2207 */
2208 public <T extends JCExpression> List<T> translate(List<T> trees, Type type) {
2209 if (trees == null) return null;
2210 for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2211 l.head = translate(l.head, type);
2212 return trees;
2213 }
2312 encl.trans_local = encl.trans_local.prepend(currentClass);
2313 }
2314
2315 // Recursively translate members, taking into account that new members
2316 // might be created during the translation and prepended to the member
2317 // list `tree.defs'.
2318 List<JCTree> seen = List.nil();
2319 while (tree.defs != seen) {
2320 List<JCTree> unseen = tree.defs;
2321 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2322 JCTree outermostMemberDefPrev = outermostMemberDef;
2323 if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
2324 l.head = translate(l.head);
2325 outermostMemberDef = outermostMemberDefPrev;
2326 }
2327 seen = unseen;
2328 }
2329
2330 // Convert a protected modifier to public, mask static modifier.
2331 if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
2332 tree.mods.flags &= ClassFlags;
2333
2334 // Convert name to flat representation, replacing '.' by '$'.
2335 tree.name = Convert.shortName(currentClass.flatName());
2336
2337 // Add free variables proxy definitions to class.
2338
2339 for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2340 tree.defs = tree.defs.prepend(l.head);
2341 enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
2342 }
2343 // If this$n was accessed, add the field definition and
2344 // update initial constructors to initialize it
2345 if (currentClass.hasOuterInstance() && shouldEmitOuterThis(currentClass)) {
2346 tree.defs = tree.defs.prepend(otdef);
2347 enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2348
2349 for (JCTree def : tree.defs) {
2350 if (TreeInfo.isInitialConstructor(def)) {
2351 JCMethodDecl mdef = (JCMethodDecl) def;
2352 mdef.body.stats = mdef.body.stats.prepend(
2722
2723 MethodType indyType = msym.type.asMethodType();
2724 indyType = new MethodType(
2725 isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
2726 indyType.restype,
2727 indyType.thrown,
2728 syms.methodClass
2729 );
2730 DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName,
2731 syms.noSymbol,
2732 bsm.asHandle(),
2733 indyType,
2734 staticArgValues);
2735 JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), argName);
2736 qualifier.sym = dynSym;
2737 qualifier.type = msym.type.asMethodType().restype;
2738 return qualifier;
2739 }
2740
2741 public void visitMethodDef(JCMethodDecl tree) {
2742 if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
2743 // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2744 // argument list for each constructor of an enum.
2745 JCVariableDecl nameParam = make_at(tree.pos()).
2746 Param(names.fromString(target.syntheticNameChar() +
2747 "enum" + target.syntheticNameChar() + "name"),
2748 syms.stringType, tree.sym);
2749 nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
2750 JCVariableDecl ordParam = make.
2751 Param(names.fromString(target.syntheticNameChar() +
2752 "enum" + target.syntheticNameChar() +
2753 "ordinal"),
2754 syms.intType, tree.sym);
2755 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
2756
2757 MethodSymbol m = tree.sym;
2758 tree.params = tree.params.prepend(ordParam).prepend(nameParam);
2759
2760 m.extraParams = m.extraParams.prepend(ordParam.sym);
2761 m.extraParams = m.extraParams.prepend(nameParam.sym);
2763 m.erasure_field = new MethodType(
2764 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
2765 olderasure.getReturnType(),
2766 olderasure.getThrownTypes(),
2767 syms.methodClass);
2768 }
2769
2770 JCMethodDecl prevMethodDef = currentMethodDef;
2771 MethodSymbol prevMethodSym = currentMethodSym;
2772 try {
2773 currentMethodDef = tree;
2774 currentMethodSym = tree.sym;
2775 visitMethodDefInternal(tree);
2776 } finally {
2777 currentMethodDef = prevMethodDef;
2778 currentMethodSym = prevMethodSym;
2779 }
2780 }
2781
2782 private void visitMethodDefInternal(JCMethodDecl tree) {
2783 if (tree.name == names.init &&
2784 !currentClass.isStatic() &&
2785 (currentClass.isInner() || currentClass.isDirectlyOrIndirectlyLocal())) {
2786 // We are seeing a constructor of an inner class.
2787 MethodSymbol m = tree.sym;
2788
2789 // Push a new proxy scope for constructor parameters.
2790 // and create definitions for any this$n and proxy parameters.
2791 Map<Symbol, Symbol> prevProxies = proxies;
2792 proxies = new HashMap<>(proxies);
2793 List<VarSymbol> prevOuterThisStack = outerThisStack;
2794 List<VarSymbol> fvs = freevars(currentClass);
2795 JCVariableDecl otdef = null;
2796 if (currentClass.hasOuterInstance())
2797 otdef = outerThisDef(tree.pos, m);
2798 List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m, PARAMETER);
2799
2800 // Recursively translate result type, parameters and thrown list.
2801 tree.restype = translate(tree.restype);
2802 tree.params = translateVarDefs(tree.params);
2803 tree.thrown = translate(tree.thrown);
2844 // pop local variables from proxy stack
2845 proxies = prevProxies;
2846
2847 // recursively translate following local statements and
2848 // combine with this- or super-call
2849 List<JCStatement> stats = translate(tree.body.stats.tail);
2850 tree.body.stats = stats.prepend(selfCall).prependList(added);
2851 outerThisStack = prevOuterThisStack;
2852 } else {
2853 Map<Symbol, Symbol> prevLambdaTranslationMap =
2854 lambdaTranslationMap;
2855 try {
2856 lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 &&
2857 tree.sym.name.startsWith(names.lambda) ?
2858 makeTranslationMap(tree) : null;
2859 super.visitMethodDef(tree);
2860 } finally {
2861 lambdaTranslationMap = prevLambdaTranslationMap;
2862 }
2863 }
2864 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2865 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2866 // lets find out if there is any field waiting to be initialized
2867 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2868 for (Symbol sym : currentClass.getEnclosedElements()) {
2869 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2870 fields.append((VarSymbol) sym);
2871 }
2872 for (VarSymbol field: fields) {
2873 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2874 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2875 make.at(tree.pos);
2876 tree.body.stats = tree.body.stats.append(
2877 make.Exec(
2878 make.Assign(
2879 make.Select(make.This(field.owner.erasure(types)), field),
2880 make.Ident(param)).setType(field.erasure(types))));
2881 // we don't need the flag at the field anymore
2882 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2883 }
2884 }
3086 List.nil() : List.of(translate(tree.detail));
3087 if (!tree.cond.type.isFalse()) {
3088 cond = makeBinary
3089 (AND,
3090 cond,
3091 makeUnary(NOT, tree.cond));
3092 }
3093 result =
3094 make.If(cond,
3095 make_at(tree).
3096 Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
3097 null);
3098 } else {
3099 result = make.Skip();
3100 }
3101 }
3102
3103 public void visitApply(JCMethodInvocation tree) {
3104 Symbol meth = TreeInfo.symbol(tree.meth);
3105 List<Type> argtypes = meth.type.getParameterTypes();
3106 if (meth.name == names.init && meth.owner == syms.enumSym)
3107 argtypes = argtypes.tail.tail;
3108 tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
3109 tree.varargsElement = null;
3110 Name methName = TreeInfo.name(tree.meth);
3111 if (meth.name==names.init) {
3112 // We are seeing a this(...) or super(...) constructor call.
3113 // If an access constructor is used, append null as a last argument.
3114 Symbol constructor = accessConstructor(tree.pos(), meth);
3115 if (constructor != meth) {
3116 tree.args = tree.args.append(makeNull());
3117 TreeInfo.setSymbol(tree.meth, constructor);
3118 }
3119
3120 // If we are calling a constructor of a local class, add
3121 // free variables after explicit constructor arguments.
3122 ClassSymbol c = (ClassSymbol)constructor.owner;
3123 if (c.isDirectlyOrIndirectlyLocal() && !c.isStatic()) {
3124 tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
3125 }
3126
3127 // If we are calling a constructor of an enum class, pass
3128 // along the name and ordinal arguments
3129 if ((c.flags_field&ENUM) != 0 || c.getQualifiedName() == names.java_lang_Enum) {
3130 List<JCVariableDecl> params = currentMethodDef.params;
3131 if (currentMethodSym.owner.hasOuterInstance())
3199 while (args.nonEmpty()) {
3200 JCExpression arg = translate(args.head, varargsElement);
3201 elems.append(arg);
3202 args = args.tail;
3203 }
3204 JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
3205 List.nil(),
3206 elems.toList());
3207 boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
3208 result.append(boxedArgs);
3209 } else {
3210 if (args.length() != 1) throw new AssertionError(args);
3211 JCExpression arg = translate(args.head, parameter);
3212 anyChanges |= (arg != args.head);
3213 result.append(arg);
3214 if (!anyChanges) return _args;
3215 }
3216 return result.toList();
3217 }
3218
3219 /** Expand a boxing or unboxing conversion if needed. */
3220 @SuppressWarnings("unchecked") // XXX unchecked
3221 <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
3222 boolean havePrimitive = tree.type.isPrimitive();
3223 if (havePrimitive == type.isPrimitive())
3224 return tree;
3225 if (havePrimitive) {
3226 Type unboxedTarget = types.unboxedType(type);
3227 if (!unboxedTarget.hasTag(NONE)) {
3228 if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
3229 tree.type = unboxedTarget.constType(tree.type.constValue());
3230 return (T)boxPrimitive(tree, types.erasure(type));
3231 } else {
3232 tree = (T)boxPrimitive(tree);
3233 }
3234 } else {
3235 tree = (T)unbox(tree, type);
3236 }
3237 return tree;
3238 }
3602 * A statement of the form
3603 *
3604 * <pre>
3605 * for ( T v : coll ) stmt ;
3606 * </pre>
3607 *
3608 * (where coll implements {@code Iterable<? extends T>}) gets translated to
3609 *
3610 * <pre>{@code
3611 * for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
3612 * T v = (T) #i.next();
3613 * stmt;
3614 * }
3615 * }</pre>
3616 *
3617 * where #i is a freshly named synthetic local variable.
3618 */
3619 private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
3620 make_at(tree.expr.pos());
3621 Type iteratorTarget = syms.objectType;
3622 Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
3623 syms.iterableType.tsym);
3624 if (iterableType.getTypeArguments().nonEmpty())
3625 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
3626 tree.expr.type = types.erasure(types.skipTypeVars(tree.expr.type, false));
3627 tree.expr = transTypes.coerce(attrEnv, tree.expr, types.erasure(iterableType));
3628 Symbol iterator = lookupMethod(tree.expr.pos(),
3629 names.iterator,
3630 tree.expr.type,
3631 List.nil());
3632 Assert.check(types.isSameType(types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)), types.erasure(syms.iteratorType)));
3633 VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
3634 types.erasure(syms.iteratorType),
3635 currentMethodSym);
3636
3637 JCStatement init = make.
3638 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
3639 .setType(types.erasure(iterator.type))));
3640
3641 Symbol hasNext = lookupMethod(tree.expr.pos(),
3642 names.hasNext,
3643 itvar.type,
3644 List.nil());
3645 JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
3646 Symbol next = lookupMethod(tree.expr.pos(),
3647 names.next,
3648 itvar.type,
3649 List.nil());
3650 JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
3651
3652 Assert.check(tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE);
3695 new MethodSymbol(tree.flags | BLOCK,
3696 names.empty, null,
3697 currentClass);
3698 }
3699 super.visitBlock(tree);
3700 currentMethodSym = oldMethodSym;
3701 }
3702
3703 public void visitDoLoop(JCDoWhileLoop tree) {
3704 tree.body = translate(tree.body);
3705 tree.cond = translate(tree.cond, syms.booleanType);
3706 result = tree;
3707 }
3708
3709 public void visitWhileLoop(JCWhileLoop tree) {
3710 tree.cond = translate(tree.cond, syms.booleanType);
3711 tree.body = translate(tree.body);
3712 result = tree;
3713 }
3714
3715 public void visitForLoop(JCForLoop tree) {
3716 tree.init = translate(tree.init);
3717 if (tree.cond != null)
3718 tree.cond = translate(tree.cond, syms.booleanType);
3719 tree.step = translate(tree.step);
3720 tree.body = translate(tree.body);
3721 result = tree;
3722 }
3723
3724 public void visitReturn(JCReturn tree) {
3725 if (tree.expr != null)
3726 tree.expr = translate(tree.expr,
3727 types.erasure(currentMethodDef
3728 .restype.type));
3729 result = tree;
3730 }
3731
3732 public void visitSwitch(JCSwitch tree) {
3733 List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.patternSwitch,
3734 tree.wasEnumSelector,
4188 tree.value = translate(tree.value, tree.target.type);
4189 result = tree;
4190 }
4191
4192 public void visitNewArray(JCNewArray tree) {
4193 tree.elemtype = translate(tree.elemtype);
4194 for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
4195 if (t.head != null) t.head = translate(t.head, syms.intType);
4196 tree.elems = translate(tree.elems, types.elemtype(tree.type));
4197 result = tree;
4198 }
4199
4200 public void visitSelect(JCFieldAccess tree) {
4201 // need to special case-access of the form C.super.x
4202 // these will always need an access method, unless C
4203 // is a default interface subclassed by the current class.
4204 boolean qualifiedSuperAccess =
4205 tree.selected.hasTag(SELECT) &&
4206 TreeInfo.name(tree.selected) == names._super &&
4207 !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
4208 tree.selected = translate(tree.selected);
4209 if (tree.name == names._class) {
4210 result = classOf(tree.selected);
4211 }
4212 else if (tree.name == names._super &&
4213 types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
4214 //default super call!! Not a classic qualified super call
4215 TypeSymbol supSym = tree.selected.type.tsym;
4216 Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
4217 result = tree;
4218 }
4219 else if (tree.name == names._this || tree.name == names._super) {
4220 result = makeThis(tree.pos(), tree.selected.type.tsym);
4221 }
4222 else
4223 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
4224 }
4225
4226 public void visitLetExpr(LetExpr tree) {
4227 tree.defs = translate(tree.defs);
4228 tree.expr = translate(tree.expr, tree.type);
4229 result = tree;
4230 }
4231
4232 // There ought to be nothing to rewrite here;
4233 // we don't generate code.
4234 public void visitAnnotation(JCAnnotation tree) {
4235 result = tree;
4236 }
|
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 @SuppressWarnings("this-escape")
109 protected Lower(Context context) {
110 context.put(lowerKey, this);
111 names = Names.instance(context);
112 log = Log.instance(context);
113 syms = Symtab.instance(context);
114 rs = Resolve.instance(context);
115 operators = Operators.instance(context);
116 chk = Check.instance(context);
117 attr = Attr.instance(context);
118 make = TreeMaker.instance(context);
119 cfolder = ConstFold.instance(context);
120 target = Target.instance(context);
121 typeEnvs = TypeEnvs.instance(context);
122 dollarAssertionsDisabled = names.
123 fromString(target.syntheticNameChar() + "assertionsDisabled");
124
125 types = Types.instance(context);
126 transTypes = TransTypes.instance(context);
127 Options options = Options.instance(context);
128 debugLower = options.isSet("debuglower");
129 pkginfoOpt = PkgInfo.get(options);
130 optimizeOuterThis =
131 target.optimizeOuterThis() ||
132 options.getBoolean("optimizeOuterThis", false);
133 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
134 Source source = Source.instance(context);
135 allowPrimitiveClasses = Source.Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
136 Preview preview = Preview.instance(context);
137 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
138 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
139 }
140
141 /** The currently enclosing class.
142 */
143 ClassSymbol currentClass;
144
145 /** A queue of all translated classes.
146 */
147 ListBuffer<JCTree> translated;
148
149 /** Environment for symbol lookup, set by translateTopLevelClass.
150 */
151 Env<AttrContext> attrEnv;
152
153 /** A hash table mapping syntax trees to their ending source positions.
154 */
155 EndPosTable endPosTable;
892
893 /** Look up a method in a given scope.
894 */
895 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
896 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
897 }
898
899 /** Anon inner classes are used as access constructor tags.
900 * accessConstructorTag will use an existing anon class if one is available,
901 * and synthesize a class (with makeEmptyClass) if one is not available.
902 * However, there is a small possibility that an existing class will not
903 * be generated as expected if it is inside a conditional with a constant
904 * expression. If that is found to be the case, create an empty class tree here.
905 */
906 private void checkAccessConstructorTags() {
907 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
908 ClassSymbol c = l.head;
909 if (isTranslatedClassAvailable(c))
910 continue;
911 // Create class definition tree.
912 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
913 c.outermostClass(), c.flatname, false);
914 swapAccessConstructorTag(c, cdec.sym);
915 translated.append(cdec);
916 }
917 }
918 // where
919 private boolean isTranslatedClassAvailable(ClassSymbol c) {
920 for (JCTree tree: translated) {
921 if (tree.hasTag(CLASSDEF)
922 && ((JCClassDecl) tree).sym == c) {
923 return true;
924 }
925 }
926 return false;
927 }
928
929 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
930 for (MethodSymbol methodSymbol : accessConstrs.values()) {
931 Assert.check(methodSymbol.type.hasTag(METHOD));
932 MethodType oldMethodType =
1129
1130 /** The qualifier to be used for accessing a symbol in an outer class.
1131 * This is either C.sym or C.this.sym, depending on whether or not
1132 * sym is static.
1133 * @param sym The accessed symbol.
1134 */
1135 JCExpression accessBase(DiagnosticPosition pos, Symbol sym) {
1136 return (sym.flags() & STATIC) != 0
1137 ? access(make.at(pos.getStartPosition()).QualIdent(sym.owner))
1138 : makeOwnerThis(pos, sym, true);
1139 }
1140
1141 /** Do we need an access method to reference private symbol?
1142 */
1143 boolean needsPrivateAccess(Symbol sym) {
1144 if (target.hasNestmateAccess()) {
1145 return false;
1146 }
1147 if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
1148 return false;
1149 } else if (names.isInitOrVNew(sym.name) && sym.owner.isDirectlyOrIndirectlyLocal()) {
1150 // private constructor in local class: relax protection
1151 sym.flags_field &= ~PRIVATE;
1152 return false;
1153 } else {
1154 return true;
1155 }
1156 }
1157
1158 /** Do we need an access method to reference symbol in other package?
1159 */
1160 boolean needsProtectedAccess(Symbol sym, JCTree tree) {
1161 if (disableProtectedAccessors) return false;
1162 if ((sym.flags() & PROTECTED) == 0 ||
1163 sym.owner.owner == currentClass.owner || // fast special case
1164 sym.packge() == currentClass.packge())
1165 return false;
1166 if (!currentClass.isSubClass(sym.owner, types))
1167 return true;
1168 if ((sym.flags() & STATIC) != 0 ||
1169 !tree.hasTag(SELECT) ||
1218 sym.owner.enclClass() != currentClass) {
1219 // A constant is replaced by its constant value.
1220 Object cv = ((VarSymbol)sym).getConstValue();
1221 if (cv != null) {
1222 make.at(tree.pos);
1223 return makeLit(sym.type, cv);
1224 }
1225 if (lambdaTranslationMap != null && lambdaTranslationMap.get(sym) != null) {
1226 return make.at(tree.pos).Ident(lambdaTranslationMap.get(sym));
1227 } else {
1228 // Otherwise replace the variable by its proxy.
1229 sym = proxies.get(sym);
1230 Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
1231 tree = make.at(tree.pos).Ident(sym);
1232 }
1233 }
1234 JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
1235 switch (sym.kind) {
1236 case TYP:
1237 if (sym.owner.kind != PCK) {
1238 // Make sure not to lose type fidelity due to symbol sharing between projections
1239 boolean requireReferenceProjection = allowPrimitiveClasses &&
1240 tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection();
1241 // Convert type idents to
1242 // <flat name> or <package name> . <flat name>
1243 Name flatname = Convert.shortName(sym.flatName());
1244 while (base != null &&
1245 TreeInfo.symbol(base) != null &&
1246 TreeInfo.symbol(base).kind != PCK) {
1247 base = (base.hasTag(SELECT))
1248 ? ((JCFieldAccess) base).selected
1249 : null;
1250 }
1251 if (tree.hasTag(IDENT)) {
1252 ((JCIdent) tree).name = flatname;
1253 } else if (base == null) {
1254 tree = make.at(tree.pos).Ident(sym);
1255 ((JCIdent) tree).name = flatname;
1256 if (requireReferenceProjection) {
1257 tree.setType(tree.type.referenceProjection());
1258 }
1259 } else {
1260 ((JCFieldAccess) tree).selected = base;
1261 ((JCFieldAccess) tree).name = flatname;
1262 if (requireReferenceProjection) {
1263 tree.setType(tree.type.referenceProjection());
1264 }
1265 }
1266 }
1267 break;
1268 case MTH: case VAR:
1269 if (sym.owner.kind == TYP) {
1270
1271 // Access methods are required for
1272 // - private members,
1273 // - protected members in a superclass of an
1274 // enclosing class contained in another package.
1275 // - all non-private members accessed via a qualified super.
1276 boolean protAccess = refSuper && !needsPrivateAccess(sym)
1277 || needsProtectedAccess(sym, tree);
1278 boolean accReq = protAccess || needsPrivateAccess(sym);
1279
1280 // A base has to be supplied for
1281 // - simple identifiers accessing variables in outer classes.
1282 boolean baseReq =
1283 base == null &&
1284 sym.owner != syms.predefClass &&
1342 JCExpression access(JCExpression tree) {
1343 Symbol sym = TreeInfo.symbol(tree);
1344 return sym == null ? tree : access(sym, tree, null, false);
1345 }
1346
1347 /** Return access constructor for a private constructor,
1348 * or the constructor itself, if no access constructor is needed.
1349 * @param pos The position to report diagnostics, if any.
1350 * @param constr The private constructor.
1351 */
1352 Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) {
1353 if (needsPrivateAccess(constr)) {
1354 ClassSymbol accOwner = constr.owner.enclClass();
1355 MethodSymbol aconstr = accessConstrs.get(constr);
1356 if (aconstr == null) {
1357 List<Type> argtypes = constr.type.getParameterTypes();
1358 if ((accOwner.flags_field & ENUM) != 0)
1359 argtypes = argtypes
1360 .prepend(syms.intType)
1361 .prepend(syms.stringType);
1362 Name constructorName = accOwner.isConcreteValueClass() ? names.vnew : names.init;
1363 aconstr = new MethodSymbol(
1364 SYNTHETIC,
1365 constructorName,
1366 new MethodType(
1367 argtypes.append(
1368 accessConstructorTag().erasure(types)),
1369 constr.type.getReturnType(),
1370 constr.type.getThrownTypes(),
1371 syms.methodClass),
1372 accOwner);
1373 enterSynthetic(pos, aconstr, accOwner.members());
1374 accessConstrs.put(constr, aconstr);
1375 accessed.append(constr);
1376 }
1377 return aconstr;
1378 } else {
1379 return constr;
1380 }
1381 }
1382
1383 /** Return an anonymous class nested in this toplevel class.
1384 */
1385 ClassSymbol accessConstructorTag() {
1386 ClassSymbol topClass = currentClass.outermostClass();
1387 ModuleSymbol topModle = topClass.packge().modle;
1388 for (int i = 1; ; i++) {
1389 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1390 target.syntheticNameChar() +
1391 i);
1392 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1393 if (ctag == null)
1394 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1395 else if (!ctag.isAnonymous())
1396 continue;
1397 // keep a record of all tags, to verify that all are generated as required
1398 accessConstrTags = accessConstrTags.prepend(ctag);
1399 return ctag;
1400 }
1401 }
1402
1403 /** Add all required access methods for a private symbol to enclosing class.
1404 * @param sym The symbol.
1405 */
1406 void makeAccessible(Symbol sym) {
1407 JCClassDecl cdef = classDef(sym.owner.enclClass());
1408 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1409 if (names.isInitOrVNew(sym.name)) {
1410 cdef.defs = cdef.defs.prepend(
1411 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1412 } else {
1413 MethodSymbol[] accessors = accessSyms.get(sym);
1414 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1415 if (accessors[i] != null)
1416 cdef.defs = cdef.defs.prepend(
1417 accessDef(cdef.pos, sym, accessors[i], i));
1418 }
1419 }
1420 }
1421
1422 /** Construct definition of an access method.
1423 * @param pos The source code position of the definition.
1424 * @param vsym The private or protected symbol.
1425 * @param accessor The access method for the symbol.
1426 * @param acode The access code.
1427 */
1428 JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) {
1429 // System.err.println("access " + vsym + " with " + accessor);//DEBUG
1602 VarSymbol outerThis =
1603 new VarSymbol(flags | NOOUTERTHIS, outerThisName(target, owner), target, owner);
1604 outerThisStack = outerThisStack.prepend(outerThis);
1605 return outerThis;
1606 }
1607
1608 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1609 JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1610 vd.vartype = access(vd.vartype);
1611 return vd;
1612 }
1613
1614 /** Definition for this$n field.
1615 * @param pos The source code position of the definition.
1616 * @param owner The method in which the definition goes.
1617 */
1618 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1619 ClassSymbol c = owner.enclClass();
1620 boolean isMandated =
1621 // Anonymous constructors
1622 (owner.isInitOrVNew() && owner.isAnonymous()) ||
1623 // Constructors of non-private inner member classes
1624 (owner.isInitOrVNew() && c.isInner() &&
1625 !c.isPrivate() && !c.isStatic());
1626 long flags =
1627 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1628 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1629 owner.extraParams = owner.extraParams.prepend(outerThis);
1630 return makeOuterThisVarDecl(pos, outerThis);
1631 }
1632
1633 /** Definition for this$n field.
1634 * @param pos The source code position of the definition.
1635 * @param owner The class in which the definition goes.
1636 */
1637 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1638 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1639 return makeOuterThisVarDecl(pos, outerThis);
1640 }
1641
1642 /** Return a list of trees that load the free variables in given list,
1643 * in reverse order.
1644 * @param pos The source code position to be used for the trees.
1801 }
1802
1803 JCStatement exceptionalRethrow = make.Throw(make.Ident(primaryException));
1804 JCBlock exceptionalCloseBlock = make.Block(0L, List.of(exceptionalCloseStatement, exceptionalRethrow));
1805 JCCatch exceptionalCatchClause = make.Catch(primaryExceptionDecl, exceptionalCloseBlock);
1806
1807 //create the main try statement with the close:
1808 JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1809 List.of(exceptionalCatchClause),
1810 finallyClause);
1811
1812 outerTry.finallyCanCompleteNormally = true;
1813 stats.add(outerTry);
1814
1815 JCBlock newBlock = make.Block(0L, stats.toList());
1816 return newBlock;
1817 }
1818
1819 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1820 // convert to AutoCloseable if needed
1821 if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) {
1822 resource = convert(resource, syms.autoCloseableType);
1823 }
1824
1825 // create resource.close() method invocation
1826 JCExpression resourceClose = makeCall(resource,
1827 names.close,
1828 List.nil());
1829 return make.Exec(resourceClose);
1830 }
1831
1832 private JCExpression makeNonNullCheck(JCExpression expression) {
1833 return makeBinary(NE, expression, makeNull());
1834 }
1835
1836 /** Construct a tree that represents the outer instance
1837 * {@code C.this}. Never pick the current `this'.
1838 * @param pos The source code position to be used for the tree.
1839 * @param c The qualifier class.
1840 */
1841 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1953 }
1954
1955 /**************************************************************************
1956 * Code for .class
1957 *************************************************************************/
1958
1959 /** Return the symbol of a class to contain a cache of
1960 * compiler-generated statics such as class$ and the
1961 * $assertionsDisabled flag. We create an anonymous nested class
1962 * (unless one already exists) and return its symbol. However,
1963 * for backward compatibility in 1.4 and earlier we use the
1964 * top-level class itself.
1965 */
1966 private ClassSymbol outerCacheClass() {
1967 ClassSymbol clazz = outermostClassDef.sym;
1968 Scope s = clazz.members();
1969 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1970 if (sym.kind == TYP &&
1971 sym.name == names.empty &&
1972 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1973 return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1974 }
1975
1976 /** Create an attributed tree of the form left.name(). */
1977 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1978 Assert.checkNonNull(left.type);
1979 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1980 TreeInfo.types(args));
1981 return make.App(make.Select(left, funcsym), args);
1982 }
1983
1984 /** The tree simulating a T.class expression.
1985 * @param clazz The tree identifying type T.
1986 */
1987 private JCExpression classOf(JCTree clazz) {
1988 return classOfType(clazz.type, clazz.pos());
1989 }
1990
1991 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1992 switch (type.getTag()) {
1993 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2005 VarSymbol sym = new VarSymbol(
2006 STATIC | PUBLIC | FINAL, names._class,
2007 syms.classType, type.tsym);
2008 return make_at(pos).Select(make.Type(type), sym);
2009 default:
2010 throw new AssertionError();
2011 }
2012 }
2013
2014 /**************************************************************************
2015 * Code for enabling/disabling assertions.
2016 *************************************************************************/
2017
2018 private ClassSymbol assertionsDisabledClassCache;
2019
2020 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
2021 */
2022 private ClassSymbol assertionsDisabledClass() {
2023 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
2024
2025 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
2026
2027 return assertionsDisabledClassCache;
2028 }
2029
2030 // This code is not particularly robust if the user has
2031 // previously declared a member named '$assertionsDisabled'.
2032 // The same faulty idiom also appears in the translation of
2033 // class literals above. We should report an error if a
2034 // previous declaration is not synthetic.
2035
2036 private JCExpression assertFlagTest(DiagnosticPosition pos) {
2037 // Outermost class may be either true class or an interface.
2038 ClassSymbol outermostClass = outermostClassDef.sym;
2039
2040 //only classes can hold a non-public field, look for a usable one:
2041 ClassSymbol container = !currentClass.isInterface() ? currentClass :
2042 assertionsDisabledClass();
2043
2044 VarSymbol assertDisabledSym =
2045 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2185 /** Visitor method: Translate a single node.
2186 * Attach the source position from the old tree to its replacement tree.
2187 */
2188 @Override
2189 public <T extends JCTree> T translate(T tree) {
2190 if (tree == null) {
2191 return null;
2192 } else {
2193 make_at(tree.pos());
2194 T result = super.translate(tree);
2195 if (endPosTable != null && result != tree) {
2196 endPosTable.replaceTree(tree, result);
2197 }
2198 return result;
2199 }
2200 }
2201
2202 /** Visitor method: Translate a single node, boxing or unboxing if needed.
2203 */
2204 public <T extends JCExpression> T translate(T tree, Type type) {
2205 return (tree == null) ? null :
2206 applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
2207 }
2208
2209 /** Visitor method: Translate tree.
2210 */
2211 public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
2212 JCExpression prevEnclOp = this.enclOp;
2213 this.enclOp = enclOp;
2214 T res = translate(tree);
2215 this.enclOp = prevEnclOp;
2216 return res;
2217 }
2218
2219 /** Visitor method: Translate list of trees.
2220 */
2221 public <T extends JCExpression> List<T> translate(List<T> trees, Type type) {
2222 if (trees == null) return null;
2223 for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2224 l.head = translate(l.head, type);
2225 return trees;
2226 }
2325 encl.trans_local = encl.trans_local.prepend(currentClass);
2326 }
2327
2328 // Recursively translate members, taking into account that new members
2329 // might be created during the translation and prepended to the member
2330 // list `tree.defs'.
2331 List<JCTree> seen = List.nil();
2332 while (tree.defs != seen) {
2333 List<JCTree> unseen = tree.defs;
2334 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2335 JCTree outermostMemberDefPrev = outermostMemberDef;
2336 if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
2337 l.head = translate(l.head);
2338 outermostMemberDef = outermostMemberDefPrev;
2339 }
2340 seen = unseen;
2341 }
2342
2343 // Convert a protected modifier to public, mask static modifier.
2344 if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
2345 tree.mods.flags &= AdjustedClassFlags;
2346
2347 // Convert name to flat representation, replacing '.' by '$'.
2348 tree.name = Convert.shortName(currentClass.flatName());
2349
2350 // Add free variables proxy definitions to class.
2351
2352 for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2353 tree.defs = tree.defs.prepend(l.head);
2354 enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
2355 }
2356 // If this$n was accessed, add the field definition and
2357 // update initial constructors to initialize it
2358 if (currentClass.hasOuterInstance() && shouldEmitOuterThis(currentClass)) {
2359 tree.defs = tree.defs.prepend(otdef);
2360 enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
2361
2362 for (JCTree def : tree.defs) {
2363 if (TreeInfo.isInitialConstructor(def)) {
2364 JCMethodDecl mdef = (JCMethodDecl) def;
2365 mdef.body.stats = mdef.body.stats.prepend(
2735
2736 MethodType indyType = msym.type.asMethodType();
2737 indyType = new MethodType(
2738 isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
2739 indyType.restype,
2740 indyType.thrown,
2741 syms.methodClass
2742 );
2743 DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName,
2744 syms.noSymbol,
2745 bsm.asHandle(),
2746 indyType,
2747 staticArgValues);
2748 JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), argName);
2749 qualifier.sym = dynSym;
2750 qualifier.type = msym.type.asMethodType().restype;
2751 return qualifier;
2752 }
2753
2754 public void visitMethodDef(JCMethodDecl tree) {
2755 // TODO - enum so is always <init>
2756 if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
2757 // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2758 // argument list for each constructor of an enum.
2759 JCVariableDecl nameParam = make_at(tree.pos()).
2760 Param(names.fromString(target.syntheticNameChar() +
2761 "enum" + target.syntheticNameChar() + "name"),
2762 syms.stringType, tree.sym);
2763 nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
2764 JCVariableDecl ordParam = make.
2765 Param(names.fromString(target.syntheticNameChar() +
2766 "enum" + target.syntheticNameChar() +
2767 "ordinal"),
2768 syms.intType, tree.sym);
2769 ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
2770
2771 MethodSymbol m = tree.sym;
2772 tree.params = tree.params.prepend(ordParam).prepend(nameParam);
2773
2774 m.extraParams = m.extraParams.prepend(ordParam.sym);
2775 m.extraParams = m.extraParams.prepend(nameParam.sym);
2777 m.erasure_field = new MethodType(
2778 olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
2779 olderasure.getReturnType(),
2780 olderasure.getThrownTypes(),
2781 syms.methodClass);
2782 }
2783
2784 JCMethodDecl prevMethodDef = currentMethodDef;
2785 MethodSymbol prevMethodSym = currentMethodSym;
2786 try {
2787 currentMethodDef = tree;
2788 currentMethodSym = tree.sym;
2789 visitMethodDefInternal(tree);
2790 } finally {
2791 currentMethodDef = prevMethodDef;
2792 currentMethodSym = prevMethodSym;
2793 }
2794 }
2795
2796 private void visitMethodDefInternal(JCMethodDecl tree) {
2797 if (names.isInitOrVNew(tree.name) &&
2798 !currentClass.isStatic() &&
2799 (currentClass.isInner() || currentClass.isDirectlyOrIndirectlyLocal())) {
2800 // We are seeing a constructor of an inner class.
2801 MethodSymbol m = tree.sym;
2802
2803 // Push a new proxy scope for constructor parameters.
2804 // and create definitions for any this$n and proxy parameters.
2805 Map<Symbol, Symbol> prevProxies = proxies;
2806 proxies = new HashMap<>(proxies);
2807 List<VarSymbol> prevOuterThisStack = outerThisStack;
2808 List<VarSymbol> fvs = freevars(currentClass);
2809 JCVariableDecl otdef = null;
2810 if (currentClass.hasOuterInstance())
2811 otdef = outerThisDef(tree.pos, m);
2812 List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m, PARAMETER);
2813
2814 // Recursively translate result type, parameters and thrown list.
2815 tree.restype = translate(tree.restype);
2816 tree.params = translateVarDefs(tree.params);
2817 tree.thrown = translate(tree.thrown);
2858 // pop local variables from proxy stack
2859 proxies = prevProxies;
2860
2861 // recursively translate following local statements and
2862 // combine with this- or super-call
2863 List<JCStatement> stats = translate(tree.body.stats.tail);
2864 tree.body.stats = stats.prepend(selfCall).prependList(added);
2865 outerThisStack = prevOuterThisStack;
2866 } else {
2867 Map<Symbol, Symbol> prevLambdaTranslationMap =
2868 lambdaTranslationMap;
2869 try {
2870 lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 &&
2871 tree.sym.name.startsWith(names.lambda) ?
2872 makeTranslationMap(tree) : null;
2873 super.visitMethodDef(tree);
2874 } finally {
2875 lambdaTranslationMap = prevLambdaTranslationMap;
2876 }
2877 }
2878 if (names.isInitOrVNew(tree.name) && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2879 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2880 // lets find out if there is any field waiting to be initialized
2881 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2882 for (Symbol sym : currentClass.getEnclosedElements()) {
2883 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2884 fields.append((VarSymbol) sym);
2885 }
2886 for (VarSymbol field: fields) {
2887 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2888 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2889 make.at(tree.pos);
2890 tree.body.stats = tree.body.stats.append(
2891 make.Exec(
2892 make.Assign(
2893 make.Select(make.This(field.owner.erasure(types)), field),
2894 make.Ident(param)).setType(field.erasure(types))));
2895 // we don't need the flag at the field anymore
2896 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2897 }
2898 }
3100 List.nil() : List.of(translate(tree.detail));
3101 if (!tree.cond.type.isFalse()) {
3102 cond = makeBinary
3103 (AND,
3104 cond,
3105 makeUnary(NOT, tree.cond));
3106 }
3107 result =
3108 make.If(cond,
3109 make_at(tree).
3110 Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
3111 null);
3112 } else {
3113 result = make.Skip();
3114 }
3115 }
3116
3117 public void visitApply(JCMethodInvocation tree) {
3118 Symbol meth = TreeInfo.symbol(tree.meth);
3119 List<Type> argtypes = meth.type.getParameterTypes();
3120 // TODO - is enum so always <init>.
3121 if (names.isInitOrVNew(meth.name) && meth.owner == syms.enumSym)
3122 argtypes = argtypes.tail.tail;
3123 tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
3124 tree.varargsElement = null;
3125 Name methName = TreeInfo.name(tree.meth);
3126 if (names.isInitOrVNew(meth.name)) {
3127 // We are seeing a this(...) or super(...) constructor call.
3128 // If an access constructor is used, append null as a last argument.
3129 Symbol constructor = accessConstructor(tree.pos(), meth);
3130 if (constructor != meth) {
3131 tree.args = tree.args.append(makeNull());
3132 TreeInfo.setSymbol(tree.meth, constructor);
3133 }
3134
3135 // If we are calling a constructor of a local class, add
3136 // free variables after explicit constructor arguments.
3137 ClassSymbol c = (ClassSymbol)constructor.owner;
3138 if (c.isDirectlyOrIndirectlyLocal() && !c.isStatic()) {
3139 tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
3140 }
3141
3142 // If we are calling a constructor of an enum class, pass
3143 // along the name and ordinal arguments
3144 if ((c.flags_field&ENUM) != 0 || c.getQualifiedName() == names.java_lang_Enum) {
3145 List<JCVariableDecl> params = currentMethodDef.params;
3146 if (currentMethodSym.owner.hasOuterInstance())
3214 while (args.nonEmpty()) {
3215 JCExpression arg = translate(args.head, varargsElement);
3216 elems.append(arg);
3217 args = args.tail;
3218 }
3219 JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
3220 List.nil(),
3221 elems.toList());
3222 boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
3223 result.append(boxedArgs);
3224 } else {
3225 if (args.length() != 1) throw new AssertionError(args);
3226 JCExpression arg = translate(args.head, parameter);
3227 anyChanges |= (arg != args.head);
3228 result.append(arg);
3229 if (!anyChanges) return _args;
3230 }
3231 return result.toList();
3232 }
3233
3234 /** Apply primitive value/reference conversions as needed */
3235 @SuppressWarnings("unchecked")
3236 <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
3237 boolean haveValue = tree.type.isPrimitiveClass();
3238 if (haveValue == type.isPrimitiveClass())
3239 return tree;
3240 // For narrowing conversion, insert a cast which should trigger a null check
3241 // For widening conversions, insert a cast if emitting a unified class file.
3242 return (T) make.TypeCast(type, tree);
3243 }
3244
3245 /** Expand a boxing or unboxing conversion if needed. */
3246 @SuppressWarnings("unchecked") // XXX unchecked
3247 <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
3248 boolean havePrimitive = tree.type.isPrimitive();
3249 if (havePrimitive == type.isPrimitive())
3250 return tree;
3251 if (havePrimitive) {
3252 Type unboxedTarget = types.unboxedType(type);
3253 if (!unboxedTarget.hasTag(NONE)) {
3254 if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
3255 tree.type = unboxedTarget.constType(tree.type.constValue());
3256 return (T)boxPrimitive(tree, types.erasure(type));
3257 } else {
3258 tree = (T)boxPrimitive(tree);
3259 }
3260 } else {
3261 tree = (T)unbox(tree, type);
3262 }
3263 return tree;
3264 }
3628 * A statement of the form
3629 *
3630 * <pre>
3631 * for ( T v : coll ) stmt ;
3632 * </pre>
3633 *
3634 * (where coll implements {@code Iterable<? extends T>}) gets translated to
3635 *
3636 * <pre>{@code
3637 * for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
3638 * T v = (T) #i.next();
3639 * stmt;
3640 * }
3641 * }</pre>
3642 *
3643 * where #i is a freshly named synthetic local variable.
3644 */
3645 private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
3646 make_at(tree.expr.pos());
3647 Type iteratorTarget = syms.objectType;
3648 Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()),
3649 syms.iterableType.tsym);
3650 if (iterableType.getTypeArguments().nonEmpty())
3651 iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
3652 tree.expr.type = types.erasure(types.skipTypeVars(tree.expr.type, false));
3653 tree.expr = transTypes.coerce(attrEnv, tree.expr, types.erasure(iterableType));
3654 Symbol iterator = lookupMethod(tree.expr.pos(),
3655 names.iterator,
3656 tree.expr.type,
3657 List.nil());
3658 Assert.check(types.isSameType(types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)), types.erasure(syms.iteratorType)));
3659 VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
3660 types.erasure(syms.iteratorType),
3661 currentMethodSym);
3662
3663 JCStatement init = make.
3664 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
3665 .setType(types.erasure(iterator.type))));
3666
3667 Symbol hasNext = lookupMethod(tree.expr.pos(),
3668 names.hasNext,
3669 itvar.type,
3670 List.nil());
3671 JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
3672 Symbol next = lookupMethod(tree.expr.pos(),
3673 names.next,
3674 itvar.type,
3675 List.nil());
3676 JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
3677
3678 Assert.check(tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE);
3721 new MethodSymbol(tree.flags | BLOCK,
3722 names.empty, null,
3723 currentClass);
3724 }
3725 super.visitBlock(tree);
3726 currentMethodSym = oldMethodSym;
3727 }
3728
3729 public void visitDoLoop(JCDoWhileLoop tree) {
3730 tree.body = translate(tree.body);
3731 tree.cond = translate(tree.cond, syms.booleanType);
3732 result = tree;
3733 }
3734
3735 public void visitWhileLoop(JCWhileLoop tree) {
3736 tree.cond = translate(tree.cond, syms.booleanType);
3737 tree.body = translate(tree.body);
3738 result = tree;
3739 }
3740
3741 public void visitWithField(JCWithField tree) {
3742 Type fieldType = tree.field.type;
3743 tree.field = translate(tree.field, tree);
3744 tree.value = translate(tree.value, fieldType); // important to use pre-translation type.
3745
3746 // If translated field is an Apply, we are
3747 // seeing an access method invocation. In this case, append
3748 // right hand side as last argument of the access method.
3749 if (tree.field.hasTag(APPLY)) {
3750 JCMethodInvocation app = (JCMethodInvocation) tree.field;
3751 app.args = List.of(tree.value).prependList(app.args);
3752 result = app;
3753 } else {
3754 result = tree;
3755 }
3756 }
3757
3758 public void visitForLoop(JCForLoop tree) {
3759 tree.init = translate(tree.init);
3760 if (tree.cond != null)
3761 tree.cond = translate(tree.cond, syms.booleanType);
3762 tree.step = translate(tree.step);
3763 tree.body = translate(tree.body);
3764 result = tree;
3765 }
3766
3767 public void visitReturn(JCReturn tree) {
3768 if (tree.expr != null)
3769 tree.expr = translate(tree.expr,
3770 types.erasure(currentMethodDef
3771 .restype.type));
3772 result = tree;
3773 }
3774
3775 public void visitSwitch(JCSwitch tree) {
3776 List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.patternSwitch,
3777 tree.wasEnumSelector,
4231 tree.value = translate(tree.value, tree.target.type);
4232 result = tree;
4233 }
4234
4235 public void visitNewArray(JCNewArray tree) {
4236 tree.elemtype = translate(tree.elemtype);
4237 for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
4238 if (t.head != null) t.head = translate(t.head, syms.intType);
4239 tree.elems = translate(tree.elems, types.elemtype(tree.type));
4240 result = tree;
4241 }
4242
4243 public void visitSelect(JCFieldAccess tree) {
4244 // need to special case-access of the form C.super.x
4245 // these will always need an access method, unless C
4246 // is a default interface subclassed by the current class.
4247 boolean qualifiedSuperAccess =
4248 tree.selected.hasTag(SELECT) &&
4249 TreeInfo.name(tree.selected) == names._super &&
4250 !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
4251 /* JDK-8269956: Where a reflective (class) literal is needed, the unqualified Point.class is
4252 * always the "primary" mirror - representing the primitive reference runtime type - thereby
4253 * always matching the behavior of Object::getClass
4254 */
4255 boolean needPrimaryMirror = tree.name == names._class && tree.selected.type.isReferenceProjection();
4256 tree.selected = translate(tree.selected);
4257 if (needPrimaryMirror && allowPrimitiveClasses && tree.selected.type.isPrimitiveClass()) {
4258 tree.selected.setType(tree.selected.type.referenceProjection());
4259 }
4260 if (tree.name == names._class) {
4261 result = classOf(tree.selected);
4262 }
4263 else if (tree.name == names._super &&
4264 types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
4265 //default super call!! Not a classic qualified super call
4266 TypeSymbol supSym = tree.selected.type.tsym;
4267 Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym));
4268 result = tree;
4269 }
4270 else if (tree.name == names._this || tree.name == names._super) {
4271 result = makeThis(tree.pos(), tree.selected.type.tsym);
4272 }
4273 else
4274 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
4275 }
4276
4277 public void visitLetExpr(LetExpr tree) {
4278 tree.defs = translate(tree.defs);
4279 tree.expr = translate(tree.expr, tree.type);
4280 result = tree;
4281 }
4282
4283 // There ought to be nothing to rewrite here;
4284 // we don't generate code.
4285 public void visitAnnotation(JCAnnotation tree) {
4286 result = tree;
4287 }
|