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