1 /*
2 * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
89 private final Symtab syms;
90 private final Resolve rs;
91 private final Operators operators;
92 private final Check chk;
93 private final Attr attr;
94 private TreeMaker make;
95 private DiagnosticPosition make_pos;
96 private final ConstFold cfolder;
97 private final Target target;
98 private final TypeEnvs typeEnvs;
99 private final Name dollarAssertionsDisabled;
100 private final Types types;
101 private final TransTypes transTypes;
102 private final boolean debugLower;
103 private final boolean disableProtectedAccessors; // experimental
104 private final PkgInfo pkginfoOpt;
105 private final boolean optimizeOuterThis;
106 private final boolean nullCheckOuterThis;
107 private final boolean useMatchException;
108 private final HashMap<TypePairs, String> typePairToName;
109 private int variableIndex = 0;
110
111 @SuppressWarnings("this-escape")
112 protected Lower(Context context) {
113 context.put(lowerKey, this);
114 names = Names.instance(context);
115 log = Log.instance(context);
116 syms = Symtab.instance(context);
117 rs = Resolve.instance(context);
118 operators = Operators.instance(context);
119 chk = Check.instance(context);
120 attr = Attr.instance(context);
121 make = TreeMaker.instance(context);
122 cfolder = ConstFold.instance(context);
123 target = Target.instance(context);
124 typeEnvs = TypeEnvs.instance(context);
125 dollarAssertionsDisabled = names.
126 fromString(target.syntheticNameChar() + "assertionsDisabled");
127
128 types = Types.instance(context);
129 transTypes = TransTypes.instance(context);
130 Options options = Options.instance(context);
131 debugLower = options.isSet("debuglower");
132 pkginfoOpt = PkgInfo.get(options);
133 optimizeOuterThis =
134 target.optimizeOuterThis() ||
135 options.getBoolean("optimizeOuterThis", false);
136 nullCheckOuterThis = options.getBoolean("nullCheckOuterThis",
137 target.nullCheckOuterThisByDefault());
138 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
139 Source source = Source.instance(context);
140 Preview preview = Preview.instance(context);
141 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
142 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
143 typePairToName = TypePairs.initialize(syms);
144 }
145
146 /** The currently enclosing class.
147 */
148 ClassSymbol currentClass;
149
150 /** A queue of all translated classes.
151 */
152 ListBuffer<JCTree> translated;
153
154 /** Environment for symbol lookup, set by translateTopLevelClass.
155 */
156 Env<AttrContext> attrEnv;
157
158 /* ************************************************************************
159 * Global mappings
160 *************************************************************************/
161
162 /** A hash table mapping local classes to their definitions.
163 */
754
755 /** Look up a method in a given scope.
756 */
757 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
758 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
759 }
760
761 /** Anon inner classes are used as access constructor tags.
762 * accessConstructorTag will use an existing anon class if one is available,
763 * and synthesize a class (with makeEmptyClass) if one is not available.
764 * However, there is a small possibility that an existing class will not
765 * be generated as expected if it is inside a conditional with a constant
766 * expression. If that is found to be the case, create an empty class tree here.
767 */
768 private void checkAccessConstructorTags() {
769 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
770 ClassSymbol c = l.head;
771 if (isTranslatedClassAvailable(c))
772 continue;
773 // Create class definition tree.
774 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
775 c.outermostClass(), c.flatname, false);
776 swapAccessConstructorTag(c, cdec.sym);
777 translated.append(cdec);
778 }
779 }
780 // where
781 private boolean isTranslatedClassAvailable(ClassSymbol c) {
782 for (JCTree tree: translated) {
783 if (tree.hasTag(CLASSDEF)
784 && ((JCClassDecl) tree).sym == c) {
785 return true;
786 }
787 }
788 return false;
789 }
790
791 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
792 for (MethodSymbol methodSymbol : accessConstrs.values()) {
793 Assert.check(methodSymbol.type.hasTag(METHOD));
794 MethodType oldMethodType =
1226 accessConstrs.put(constr, aconstr);
1227 accessed.append(constr);
1228 }
1229 return aconstr;
1230 } else {
1231 return constr;
1232 }
1233 }
1234
1235 /** Return an anonymous class nested in this toplevel class.
1236 */
1237 ClassSymbol accessConstructorTag() {
1238 ClassSymbol topClass = currentClass.outermostClass();
1239 ModuleSymbol topModle = topClass.packge().modle;
1240 for (int i = 1; ; i++) {
1241 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1242 target.syntheticNameChar() +
1243 i);
1244 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1245 if (ctag == null)
1246 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
1247 else if (!ctag.isAnonymous())
1248 continue;
1249 // keep a record of all tags, to verify that all are generated as required
1250 accessConstrTags = accessConstrTags.prepend(ctag);
1251 return ctag;
1252 }
1253 }
1254
1255 /** Add all required access methods for a private symbol to enclosing class.
1256 * @param sym The symbol.
1257 */
1258 void makeAccessible(Symbol sym) {
1259 JCClassDecl cdef = classDef(sym.owner.enclClass());
1260 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1261 if (sym.name == names.init) {
1262 cdef.defs = cdef.defs.prepend(
1263 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1264 } else {
1265 MethodSymbol[] accessors = accessSyms.get(sym);
1266 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1382
1383 /** A stack containing the this$n field of the currently translated
1384 * classes (if needed) in innermost first order.
1385 * Inside a constructor, proxies and any this$n symbol are duplicated
1386 * in an additional innermost scope, where they represent the constructor
1387 * parameters.
1388 */
1389 List<VarSymbol> outerThisStack;
1390
1391 /** The name of a free variable proxy.
1392 */
1393 Name proxyName(Name name, int index) {
1394 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1395 if (index > 0) {
1396 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1397 }
1398 return proxyName;
1399 }
1400
1401 /** Proxy definitions for all free variables in given list, in reverse order.
1402 * @param pos The source code position of the definition.
1403 * @param freevars The free variables.
1404 * @param owner The class in which the definitions go.
1405 */
1406 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1407 return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1408 }
1409
1410 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1411 long additionalFlags) {
1412 long flags = FINAL | SYNTHETIC | additionalFlags;
1413 List<JCVariableDecl> defs = List.nil();
1414 Set<Name> proxyNames = new HashSet<>();
1415 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1416 VarSymbol v = l.head;
1417 int index = 0;
1418 Name proxyName;
1419 do {
1420 proxyName = proxyName(v.name, index++);
1421 } while (!proxyNames.add(proxyName));
1422 VarSymbol proxy = new VarSymbol(
1423 flags, proxyName, v.erasure(types), owner) {
1424 @Override
1425 public Symbol baseSymbol() {
1426 return v;
1427 }
1435 }
1436
1437 /** The name of a this$n field
1438 * @param type The class referenced by the this$n field
1439 */
1440 Name outerThisName(Type type, Symbol owner) {
1441 Type t = type.getEnclosingType();
1442 int nestingLevel = 0;
1443 while (t.hasTag(CLASS)) {
1444 t = t.getEnclosingType();
1445 nestingLevel++;
1446 }
1447 Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
1448 while (owner.kind == TYP && ((ClassSymbol)owner).members().findFirst(result) != null)
1449 result = names.fromString(result.toString() + target.syntheticNameChar());
1450 return result;
1451 }
1452
1453 private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
1454 Type target = owner.innermostAccessibleEnclosingClass().erasure(types);
1455 // Set NOOUTERTHIS for all synthetic outer instance variables, and unset
1456 // it when the variable is accessed. If the variable is never accessed,
1457 // we skip creating an outer instance field and saving the constructor
1458 // parameter to it.
1459 VarSymbol outerThis =
1460 new VarSymbol(flags | NOOUTERTHIS, outerThisName(target, owner), target, owner);
1461 outerThisStack = outerThisStack.prepend(outerThis);
1462 return outerThis;
1463 }
1464
1465 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1466 JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1467 vd.vartype = access(vd.vartype);
1468 return vd;
1469 }
1470
1471 /** Definition for this$n field.
1472 * @param pos The source code position of the definition.
1473 * @param owner The method in which the definition goes.
1474 */
1475 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1476 ClassSymbol c = owner.enclClass();
1477 boolean isMandated =
1478 // Anonymous constructors
1479 (owner.isConstructor() && owner.isAnonymous()) ||
1480 // Constructors of non-private inner member classes
1481 (owner.isConstructor() && c.isInner() &&
1482 !c.isPrivate() && !c.isStatic());
1483 long flags =
1484 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1485 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1486 owner.extraParams = owner.extraParams.prepend(outerThis);
1487 return makeOuterThisVarDecl(pos, outerThis);
1488 }
1489
1490 /** Definition for this$n field.
1491 * @param pos The source code position of the definition.
1492 * @param owner The class in which the definition goes.
1493 */
1494 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1495 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1496 return makeOuterThisVarDecl(pos, outerThis);
1497 }
1498
1499 /** Return a list of trees that load the free variables in given list,
1500 * in reverse order.
1501 * @param pos The source code position to be used for the trees.
1502 * @param freevars The list of free variables.
1503 */
1504 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1505 List<JCExpression> args = List.nil();
1506 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1507 args = args.prepend(loadFreevar(pos, l.head));
1508 return args;
1509 }
1510 //where
1511 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1512 return access(v, make.at(pos).Ident(v), null, false);
1513 }
1514
1515 /** Construct a tree simulating the expression {@code C.this}.
1815 }
1816
1817 /* ************************************************************************
1818 * Code for .class
1819 *************************************************************************/
1820
1821 /** Return the symbol of a class to contain a cache of
1822 * compiler-generated statics such as class$ and the
1823 * $assertionsDisabled flag. We create an anonymous nested class
1824 * (unless one already exists) and return its symbol. However,
1825 * for backward compatibility in 1.4 and earlier we use the
1826 * top-level class itself.
1827 */
1828 private ClassSymbol outerCacheClass() {
1829 ClassSymbol clazz = outermostClassDef.sym;
1830 Scope s = clazz.members();
1831 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1832 if (sym.kind == TYP &&
1833 sym.name == names.empty &&
1834 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1835 return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
1836 }
1837
1838 /** Create an attributed tree of the form left.name(). */
1839 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1840 Assert.checkNonNull(left.type);
1841 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1842 TreeInfo.types(args));
1843 return make.App(make.Select(left, funcsym), args);
1844 }
1845
1846 /** The tree simulating a T.class expression.
1847 * @param clazz The tree identifying type T.
1848 */
1849 private JCExpression classOf(JCTree clazz) {
1850 return classOfType(clazz.type, clazz.pos());
1851 }
1852
1853 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1854 switch (type.getTag()) {
1855 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1856 case DOUBLE: case BOOLEAN: case VOID:
1857 // replace with <BoxedClass>.TYPE
1858 ClassSymbol c = types.boxedClass(type);
1859 Symbol typeSym =
1860 rs.accessBase(
1861 rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR),
1862 pos, c.type, names.TYPE, true);
1863 if (typeSym.kind == VAR)
1864 ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
1865 return make.QualIdent(typeSym);
1866 case CLASS: case ARRAY:
1867 VarSymbol sym = new VarSymbol(
1868 STATIC | PUBLIC | FINAL, names._class,
1869 syms.classType, type.tsym);
1870 return make_at(pos).Select(make.Type(type), sym);
1871 default:
1872 throw new AssertionError();
1873 }
1874 }
1875
1876 /* ************************************************************************
1877 * Code for enabling/disabling assertions.
1878 *************************************************************************/
1879
1880 private ClassSymbol assertionsDisabledClassCache;
1881
1882 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1883 */
1884 private ClassSymbol assertionsDisabledClass() {
1885 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1886
1887 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
1888
1889 return assertionsDisabledClassCache;
1890 }
1891
1892 // This code is not particularly robust if the user has
1893 // previously declared a member named '$assertionsDisabled'.
1894 // The same faulty idiom also appears in the translation of
1895 // class literals above. We should report an error if a
1896 // previous declaration is not synthetic.
1897
1898 private JCExpression assertFlagTest(DiagnosticPosition pos) {
1899 // Outermost class may be either true class or an interface.
1900 ClassSymbol outermostClass = outermostClassDef.sym;
1901
1902 //only classes can hold a non-public field, look for a usable one:
1903 ClassSymbol container = !currentClass.isInterface() ? currentClass :
1904 assertionsDisabledClass();
1905
1906 VarSymbol assertDisabledSym =
1907 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2736 if (added.nonEmpty()) {
2737 List<JCStatement> initializers = added.toList();
2738 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2739 }
2740
2741 // pop local variables from proxy stack
2742 proxies = prevProxies;
2743
2744 outerThisStack = prevOuterThisStack;
2745 } else {
2746 super.visitMethodDef(tree);
2747 }
2748 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2749 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2750 // lets find out if there is any field waiting to be initialized
2751 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2752 for (Symbol sym : currentClass.getEnclosedElements()) {
2753 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2754 fields.append((VarSymbol) sym);
2755 }
2756 for (VarSymbol field: fields) {
2757 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2758 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2759 make.at(tree.pos);
2760 tree.body.stats = tree.body.stats.append(
2761 make.Exec(
2762 make.Assign(
2763 make.Select(make.This(field.owner.erasure(types)), field),
2764 make.Ident(param)).setType(field.erasure(types))));
2765 // we don't need the flag at the field anymore
2766 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2767 }
2768 }
2769 }
2770 result = tree;
2771 }
2772
2773 public void visitTypeCast(JCTypeCast tree) {
2774 tree.clazz = translate(tree.clazz);
2775 if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2776 tree.expr = translate(tree.expr, tree.type);
2777 else
2778 tree.expr = translate(tree.expr);
2779 result = tree;
2780 }
2781
2782 /**
2783 * All the exactness checks between primitive types that require a run-time
2784 * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2785 * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2786 * {@code S} and {@code T} are primitive types and correspond to the runtime
2787 * action that will be executed to check whether a certain value (that is passed
2788 * as a parameter) can be converted to {@code T} without loss of information.
|
1 /*
2 * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
89 private final Symtab syms;
90 private final Resolve rs;
91 private final Operators operators;
92 private final Check chk;
93 private final Attr attr;
94 private TreeMaker make;
95 private DiagnosticPosition make_pos;
96 private final ConstFold cfolder;
97 private final Target target;
98 private final TypeEnvs typeEnvs;
99 private final Name dollarAssertionsDisabled;
100 private final Types types;
101 private final TransTypes transTypes;
102 private final boolean debugLower;
103 private final boolean disableProtectedAccessors; // experimental
104 private final PkgInfo pkginfoOpt;
105 private final boolean optimizeOuterThis;
106 private final boolean nullCheckOuterThis;
107 private final boolean useMatchException;
108 private final HashMap<TypePairs, String> typePairToName;
109 private final boolean allowValueClasses;
110 private int variableIndex = 0;
111
112 @SuppressWarnings("this-escape")
113 protected Lower(Context context) {
114 context.put(lowerKey, this);
115 names = Names.instance(context);
116 log = Log.instance(context);
117 syms = Symtab.instance(context);
118 rs = Resolve.instance(context);
119 operators = Operators.instance(context);
120 chk = Check.instance(context);
121 attr = Attr.instance(context);
122 make = TreeMaker.instance(context);
123 cfolder = ConstFold.instance(context);
124 target = Target.instance(context);
125 typeEnvs = TypeEnvs.instance(context);
126 dollarAssertionsDisabled = names.
127 fromString(target.syntheticNameChar() + "assertionsDisabled");
128
129 types = Types.instance(context);
130 transTypes = TransTypes.instance(context);
131 Options options = Options.instance(context);
132 debugLower = options.isSet("debuglower");
133 pkginfoOpt = PkgInfo.get(options);
134 optimizeOuterThis =
135 target.optimizeOuterThis() ||
136 options.getBoolean("optimizeOuterThis", false);
137 nullCheckOuterThis = options.getBoolean("nullCheckOuterThis",
138 target.nullCheckOuterThisByDefault());
139 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
140 Source source = Source.instance(context);
141 Preview preview = Preview.instance(context);
142 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
143 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
144 typePairToName = TypePairs.initialize(syms);
145 this.allowValueClasses = preview.isEnabled() && Feature.VALUE_CLASSES.allowedInSource(source);
146 }
147
148 /** The currently enclosing class.
149 */
150 ClassSymbol currentClass;
151
152 /** A queue of all translated classes.
153 */
154 ListBuffer<JCTree> translated;
155
156 /** Environment for symbol lookup, set by translateTopLevelClass.
157 */
158 Env<AttrContext> attrEnv;
159
160 /* ************************************************************************
161 * Global mappings
162 *************************************************************************/
163
164 /** A hash table mapping local classes to their definitions.
165 */
756
757 /** Look up a method in a given scope.
758 */
759 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
760 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
761 }
762
763 /** Anon inner classes are used as access constructor tags.
764 * accessConstructorTag will use an existing anon class if one is available,
765 * and synthesize a class (with makeEmptyClass) if one is not available.
766 * However, there is a small possibility that an existing class will not
767 * be generated as expected if it is inside a conditional with a constant
768 * expression. If that is found to be the case, create an empty class tree here.
769 */
770 private void checkAccessConstructorTags() {
771 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
772 ClassSymbol c = l.head;
773 if (isTranslatedClassAvailable(c))
774 continue;
775 // Create class definition tree.
776 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
777 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
778 c.outermostClass(), c.flatname, false);
779 swapAccessConstructorTag(c, cdec.sym);
780 translated.append(cdec);
781 }
782 }
783 // where
784 private boolean isTranslatedClassAvailable(ClassSymbol c) {
785 for (JCTree tree: translated) {
786 if (tree.hasTag(CLASSDEF)
787 && ((JCClassDecl) tree).sym == c) {
788 return true;
789 }
790 }
791 return false;
792 }
793
794 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
795 for (MethodSymbol methodSymbol : accessConstrs.values()) {
796 Assert.check(methodSymbol.type.hasTag(METHOD));
797 MethodType oldMethodType =
1229 accessConstrs.put(constr, aconstr);
1230 accessed.append(constr);
1231 }
1232 return aconstr;
1233 } else {
1234 return constr;
1235 }
1236 }
1237
1238 /** Return an anonymous class nested in this toplevel class.
1239 */
1240 ClassSymbol accessConstructorTag() {
1241 ClassSymbol topClass = currentClass.outermostClass();
1242 ModuleSymbol topModle = topClass.packge().modle;
1243 for (int i = 1; ; i++) {
1244 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1245 target.syntheticNameChar() +
1246 i);
1247 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1248 if (ctag == null)
1249 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1250 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1251 else if (!ctag.isAnonymous())
1252 continue;
1253 // keep a record of all tags, to verify that all are generated as required
1254 accessConstrTags = accessConstrTags.prepend(ctag);
1255 return ctag;
1256 }
1257 }
1258
1259 /** Add all required access methods for a private symbol to enclosing class.
1260 * @param sym The symbol.
1261 */
1262 void makeAccessible(Symbol sym) {
1263 JCClassDecl cdef = classDef(sym.owner.enclClass());
1264 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1265 if (sym.name == names.init) {
1266 cdef.defs = cdef.defs.prepend(
1267 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1268 } else {
1269 MethodSymbol[] accessors = accessSyms.get(sym);
1270 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1386
1387 /** A stack containing the this$n field of the currently translated
1388 * classes (if needed) in innermost first order.
1389 * Inside a constructor, proxies and any this$n symbol are duplicated
1390 * in an additional innermost scope, where they represent the constructor
1391 * parameters.
1392 */
1393 List<VarSymbol> outerThisStack;
1394
1395 /** The name of a free variable proxy.
1396 */
1397 Name proxyName(Name name, int index) {
1398 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1399 if (index > 0) {
1400 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1401 }
1402 return proxyName;
1403 }
1404
1405 /** Proxy definitions for all free variables in given list, in reverse order.
1406 * @param pos The source code position of the definition.
1407 * @param freevars The free variables.
1408 * @param owner The class in which the definitions go.
1409 */
1410 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1411 long strict = (allowValueClasses && owner.isValueClass()) ? STRICT : 0;
1412 return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD | strict);
1413 }
1414
1415 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1416 long additionalFlags) {
1417 long flags = FINAL | SYNTHETIC | additionalFlags;
1418 List<JCVariableDecl> defs = List.nil();
1419 Set<Name> proxyNames = new HashSet<>();
1420 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1421 VarSymbol v = l.head;
1422 int index = 0;
1423 Name proxyName;
1424 do {
1425 proxyName = proxyName(v.name, index++);
1426 } while (!proxyNames.add(proxyName));
1427 VarSymbol proxy = new VarSymbol(
1428 flags, proxyName, v.erasure(types), owner) {
1429 @Override
1430 public Symbol baseSymbol() {
1431 return v;
1432 }
1440 }
1441
1442 /** The name of a this$n field
1443 * @param type The class referenced by the this$n field
1444 */
1445 Name outerThisName(Type type, Symbol owner) {
1446 Type t = type.getEnclosingType();
1447 int nestingLevel = 0;
1448 while (t.hasTag(CLASS)) {
1449 t = t.getEnclosingType();
1450 nestingLevel++;
1451 }
1452 Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
1453 while (owner.kind == TYP && ((ClassSymbol)owner).members().findFirst(result) != null)
1454 result = names.fromString(result.toString() + target.syntheticNameChar());
1455 return result;
1456 }
1457
1458 private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
1459 Type target = owner.innermostAccessibleEnclosingClass().erasure(types);
1460 if (owner.kind == TYP) {
1461 // Set NOOUTERTHIS for all synthetic outer instance variables, and unset
1462 // it when the variable is accessed. If the variable is never accessed,
1463 // we skip creating an outer instance field and saving the constructor
1464 // parameter to it.
1465 flags = flags | NOOUTERTHIS | OUTER_THIS_FIELD;
1466 }
1467 VarSymbol outerThis = new VarSymbol(flags, outerThisName(target, owner), target, owner);
1468 outerThisStack = outerThisStack.prepend(outerThis);
1469 return outerThis;
1470 }
1471
1472 private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1473 JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1474 vd.vartype = access(vd.vartype);
1475 return vd;
1476 }
1477
1478 /** Definition for this$n field.
1479 * @param pos The source code position of the definition.
1480 * @param owner The method in which the definition goes.
1481 */
1482 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1483 ClassSymbol c = owner.enclClass();
1484 boolean isMandated =
1485 // Anonymous constructors
1486 (owner.isConstructor() && owner.isAnonymous()) ||
1487 // Constructors of non-private inner member classes
1488 (owner.isConstructor() && c.isInner() &&
1489 !c.isPrivate() && !c.isStatic());
1490 long flags =
1491 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1492 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1493 owner.extraParams = owner.extraParams.prepend(outerThis);
1494 return makeOuterThisVarDecl(pos, outerThis);
1495 }
1496
1497 /** Definition for this$n field.
1498 * @param pos The source code position of the definition.
1499 * @param owner The class in which the definition goes.
1500 */
1501 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1502 long strict = (allowValueClasses && owner.isValueClass()) ? STRICT : 0;
1503 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | strict);
1504 return makeOuterThisVarDecl(pos, outerThis);
1505 }
1506
1507 /** Return a list of trees that load the free variables in given list,
1508 * in reverse order.
1509 * @param pos The source code position to be used for the trees.
1510 * @param freevars The list of free variables.
1511 */
1512 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1513 List<JCExpression> args = List.nil();
1514 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1515 args = args.prepend(loadFreevar(pos, l.head));
1516 return args;
1517 }
1518 //where
1519 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1520 return access(v, make.at(pos).Ident(v), null, false);
1521 }
1522
1523 /** Construct a tree simulating the expression {@code C.this}.
1823 }
1824
1825 /* ************************************************************************
1826 * Code for .class
1827 *************************************************************************/
1828
1829 /** Return the symbol of a class to contain a cache of
1830 * compiler-generated statics such as class$ and the
1831 * $assertionsDisabled flag. We create an anonymous nested class
1832 * (unless one already exists) and return its symbol. However,
1833 * for backward compatibility in 1.4 and earlier we use the
1834 * top-level class itself.
1835 */
1836 private ClassSymbol outerCacheClass() {
1837 ClassSymbol clazz = outermostClassDef.sym;
1838 Scope s = clazz.members();
1839 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1840 if (sym.kind == TYP &&
1841 sym.name == names.empty &&
1842 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1843 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1844 return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1845 }
1846
1847 /** Create an attributed tree of the form left.name(). */
1848 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1849 Assert.checkNonNull(left.type);
1850 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1851 TreeInfo.types(args));
1852 return make.App(make.Select(left, funcsym), args);
1853 }
1854
1855 /** The tree simulating a T.class expression.
1856 * @param clazz The tree identifying type T.
1857 */
1858 private JCExpression classOf(JCTree clazz) {
1859 return classOfType(clazz.type, clazz.pos());
1860 }
1861
1862 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1863 switch (type.getTag()) {
1864 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1865 case DOUBLE: case BOOLEAN: case VOID:
1866 // replace with <BoxedClass>.TYPE
1867 ClassSymbol c = types.boxedClass(type);
1868 Symbol typeSym =
1869 rs.accessBase(
1870 rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR, null),
1871 pos, c.type, names.TYPE, true);
1872 if (typeSym.kind == VAR)
1873 ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
1874 return make.QualIdent(typeSym);
1875 case CLASS: case ARRAY:
1876 VarSymbol sym = new VarSymbol(
1877 STATIC | PUBLIC | FINAL, names._class,
1878 syms.classType, type.tsym);
1879 return make_at(pos).Select(make.Type(type), sym);
1880 default:
1881 throw new AssertionError();
1882 }
1883 }
1884
1885 /* ************************************************************************
1886 * Code for enabling/disabling assertions.
1887 *************************************************************************/
1888
1889 private ClassSymbol assertionsDisabledClassCache;
1890
1891 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1892 */
1893 private ClassSymbol assertionsDisabledClass() {
1894 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1895
1896 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1897 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1898
1899 return assertionsDisabledClassCache;
1900 }
1901
1902 // This code is not particularly robust if the user has
1903 // previously declared a member named '$assertionsDisabled'.
1904 // The same faulty idiom also appears in the translation of
1905 // class literals above. We should report an error if a
1906 // previous declaration is not synthetic.
1907
1908 private JCExpression assertFlagTest(DiagnosticPosition pos) {
1909 // Outermost class may be either true class or an interface.
1910 ClassSymbol outermostClass = outermostClassDef.sym;
1911
1912 //only classes can hold a non-public field, look for a usable one:
1913 ClassSymbol container = !currentClass.isInterface() ? currentClass :
1914 assertionsDisabledClass();
1915
1916 VarSymbol assertDisabledSym =
1917 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2746 if (added.nonEmpty()) {
2747 List<JCStatement> initializers = added.toList();
2748 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2749 }
2750
2751 // pop local variables from proxy stack
2752 proxies = prevProxies;
2753
2754 outerThisStack = prevOuterThisStack;
2755 } else {
2756 super.visitMethodDef(tree);
2757 }
2758 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2759 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2760 // lets find out if there is any field waiting to be initialized
2761 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2762 for (Symbol sym : currentClass.getEnclosedElements()) {
2763 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2764 fields.append((VarSymbol) sym);
2765 }
2766 ListBuffer<JCStatement> initializers = new ListBuffer<>();
2767 for (VarSymbol field: fields) {
2768 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2769 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2770 make.at(tree.pos);
2771 initializers.add(make.Exec(
2772 make.Assign(
2773 make.Select(make.This(field.owner.erasure(types)), field),
2774 make.Ident(param)).setType(field.erasure(types))));
2775 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2776 }
2777 }
2778 if (initializers.nonEmpty()) {
2779 if (allowValueClasses && (tree.sym.owner.isValueClass() || ((ClassSymbol)tree.sym.owner).isRecord())) {
2780 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2781 } else {
2782 tree.body.stats = tree.body.stats.appendList(initializers);
2783 }
2784 }
2785 }
2786 result = tree;
2787 }
2788
2789 public void visitTypeCast(JCTypeCast tree) {
2790 tree.clazz = translate(tree.clazz);
2791 if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2792 tree.expr = translate(tree.expr, tree.type);
2793 else
2794 tree.expr = translate(tree.expr);
2795 result = tree;
2796 }
2797
2798 /**
2799 * All the exactness checks between primitive types that require a run-time
2800 * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2801 * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2802 * {@code S} and {@code T} are primitive types and correspond to the runtime
2803 * action that will be executed to check whether a certain value (that is passed
2804 * as a parameter) can be converted to {@code T} without loss of information.
|