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 */
176 * The current expected return type.
177 */
178 Type currentRestype;
179
180 /** The current method definition.
181 */
182 JCMethodDecl currentMethodDef;
183
184 /** The current method symbol.
185 */
186 MethodSymbol currentMethodSym;
187
188 /** The currently enclosing outermost class definition.
189 */
190 JCClassDecl outermostClassDef;
191
192 /** The currently enclosing outermost member definition.
193 */
194 JCTree outermostMemberDef;
195
196 /** A navigator class for assembling a mapping from local class symbols
197 * to class definition trees.
198 * There is only one case; all other cases simply traverse down the tree.
199 */
200 class ClassMap extends TreeScanner {
201
202 /** All encountered class defs are entered into classdefs table.
203 */
204 public void visitClassDef(JCClassDecl tree) {
205 classdefs.put(tree.sym, tree);
206 super.visitClassDef(tree);
207 }
208 }
209 ClassMap classMap = new ClassMap();
210
211 /** Map a class symbol to its definition.
212 * @param c The class symbol of which we want to determine the definition.
213 */
214 JCClassDecl classDef(ClassSymbol c) {
215 // First lookup the class in the classdefs table.
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
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:
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,
2155 proxies = new HashMap<>(proxies);
2156 List<VarSymbol> prevOuterThisStack = outerThisStack;
2157
2158 // If this is an enum definition
2159 if ((tree.mods.flags & ENUM) != 0 &&
2160 (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2161 visitEnumDef(tree);
2162
2163 if ((tree.mods.flags & RECORD) != 0) {
2164 visitRecordDef(tree);
2165 }
2166
2167 // If this is a nested class, define a this$n field for
2168 // it and add to proxies.
2169 JCVariableDecl otdef = null;
2170 if (currentClass.hasOuterInstance())
2171 otdef = outerThisDef(tree.pos, currentClass);
2172
2173 // If this is a local class, define proxies for all its free variables.
2174 List<JCVariableDecl> fvdefs = freevarDefs(
2175 tree.pos, freevars(currentClass), currentClass);
2176
2177 // Recursively translate superclass, interfaces.
2178 tree.extending = translate(tree.extending);
2179 tree.implementing = translate(tree.implementing);
2180
2181 if (currentClass.isDirectlyOrIndirectlyLocal()) {
2182 ClassSymbol encl = currentClass.owner.enclClass();
2183 if (encl.trans_local == null) {
2184 encl.trans_local = List.nil();
2185 }
2186 encl.trans_local = encl.trans_local.prepend(currentClass);
2187 }
2188
2189 // Recursively translate members, taking into account that new members
2190 // might be created during the translation and prepended to the member
2191 // list `tree.defs'.
2192 List<JCTree> seen = List.nil();
2193 while (tree.defs != seen) {
2194 List<JCTree> unseen = tree.defs;
2195 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
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.
2972 Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2973 if (constructor != tree.constructor) {
2974 tree.args = tree.args.append(makeNull());
2975 tree.constructor = constructor;
2976 }
2977
2978 // If created class has an outer instance, and new is qualified, pass
2979 // qualifier as first argument. If new is not qualified, pass the
2980 // correct outer instance as first argument.
2981 if (c.hasOuterInstance()) {
2982 JCExpression thisArg;
2983 if (tree.encl != null) {
2984 thisArg = attr.makeNullCheck(translate(tree.encl));
2985 thisArg.type = tree.encl.type;
2986 } else if (c.isDirectlyOrIndirectlyLocal()) {
2987 // local class
2988 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2989 } else {
2990 // nested class
2991 thisArg = makeOwnerThis(tree.pos(), c, false);
2992 }
2993 tree.args = tree.args.prepend(thisArg);
2994 }
2995 tree.encl = null;
2996
2997 // If we have an anonymous class, create its flat version, rather
2998 // than the class or interface following new.
2999 if (tree.def != null) {
3000 translate(tree.def);
3001
3002 tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3003 tree.def = null;
3004 } else {
3005 tree.clazz = access(c, tree.clazz, enclOp, false);
3006 }
3007 result = tree;
3008 }
3009
3010 // Simplify conditionals with known constant controlling expressions.
3011 // This allows us to avoid generating supporting declarations for
|
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.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
146 Feature.VALUE_CLASSES.allowedInSource(source);
147 }
148
149 /** The currently enclosing class.
150 */
151 ClassSymbol currentClass;
152
153 /** A queue of all translated classes.
154 */
155 ListBuffer<JCTree> translated;
156
157 /** Environment for symbol lookup, set by translateTopLevelClass.
158 */
159 Env<AttrContext> attrEnv;
160
161 /* ************************************************************************
162 * Global mappings
163 *************************************************************************/
164
165 /** A hash table mapping local classes to their definitions.
166 */
179 * The current expected return type.
180 */
181 Type currentRestype;
182
183 /** The current method definition.
184 */
185 JCMethodDecl currentMethodDef;
186
187 /** The current method symbol.
188 */
189 MethodSymbol currentMethodSym;
190
191 /** The currently enclosing outermost class definition.
192 */
193 JCClassDecl outermostClassDef;
194
195 /** The currently enclosing outermost member definition.
196 */
197 JCTree outermostMemberDef;
198
199 /** A hash table mapping local classes to a set of outer this fields
200 */
201 public Map<ClassSymbol, Set<JCExpression>> initializerOuterThis = new WeakHashMap<>();
202
203 /** A navigator class for assembling a mapping from local class symbols
204 * to class definition trees.
205 * There is only one case; all other cases simply traverse down the tree.
206 */
207 class ClassMap extends TreeScanner {
208
209 /** All encountered class defs are entered into classdefs table.
210 */
211 public void visitClassDef(JCClassDecl tree) {
212 classdefs.put(tree.sym, tree);
213 super.visitClassDef(tree);
214 }
215 }
216 ClassMap classMap = new ClassMap();
217
218 /** Map a class symbol to its definition.
219 * @param c The class symbol of which we want to determine the definition.
220 */
221 JCClassDecl classDef(ClassSymbol c) {
222 // First lookup the class in the classdefs table.
761
762 /** Look up a method in a given scope.
763 */
764 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
765 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
766 }
767
768 /** Anon inner classes are used as access constructor tags.
769 * accessConstructorTag will use an existing anon class if one is available,
770 * and synthesize a class (with makeEmptyClass) if one is not available.
771 * However, there is a small possibility that an existing class will not
772 * be generated as expected if it is inside a conditional with a constant
773 * expression. If that is found to be the case, create an empty class tree here.
774 */
775 private void checkAccessConstructorTags() {
776 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
777 ClassSymbol c = l.head;
778 if (isTranslatedClassAvailable(c))
779 continue;
780 // Create class definition tree.
781 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
782 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
783 c.outermostClass(), c.flatname, false);
784 swapAccessConstructorTag(c, cdec.sym);
785 translated.append(cdec);
786 }
787 }
788 // where
789 private boolean isTranslatedClassAvailable(ClassSymbol c) {
790 for (JCTree tree: translated) {
791 if (tree.hasTag(CLASSDEF)
792 && ((JCClassDecl) tree).sym == c) {
793 return true;
794 }
795 }
796 return false;
797 }
798
799 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
800 for (MethodSymbol methodSymbol : accessConstrs.values()) {
801 Assert.check(methodSymbol.type.hasTag(METHOD));
802 MethodType oldMethodType =
1234 accessConstrs.put(constr, aconstr);
1235 accessed.append(constr);
1236 }
1237 return aconstr;
1238 } else {
1239 return constr;
1240 }
1241 }
1242
1243 /** Return an anonymous class nested in this toplevel class.
1244 */
1245 ClassSymbol accessConstructorTag() {
1246 ClassSymbol topClass = currentClass.outermostClass();
1247 ModuleSymbol topModle = topClass.packge().modle;
1248 for (int i = 1; ; i++) {
1249 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1250 target.syntheticNameChar() +
1251 i);
1252 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1253 if (ctag == null)
1254 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1255 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1256 else if (!ctag.isAnonymous())
1257 continue;
1258 // keep a record of all tags, to verify that all are generated as required
1259 accessConstrTags = accessConstrTags.prepend(ctag);
1260 return ctag;
1261 }
1262 }
1263
1264 /** Add all required access methods for a private symbol to enclosing class.
1265 * @param sym The symbol.
1266 */
1267 void makeAccessible(Symbol sym) {
1268 JCClassDecl cdef = classDef(sym.owner.enclClass());
1269 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1270 if (sym.name == names.init) {
1271 cdef.defs = cdef.defs.prepend(
1272 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1273 } else {
1274 MethodSymbol[] accessors = accessSyms.get(sym);
1275 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1391
1392 /** A stack containing the this$n field of the currently translated
1393 * classes (if needed) in innermost first order.
1394 * Inside a constructor, proxies and any this$n symbol are duplicated
1395 * in an additional innermost scope, where they represent the constructor
1396 * parameters.
1397 */
1398 List<VarSymbol> outerThisStack;
1399
1400 /** The name of a free variable proxy.
1401 */
1402 Name proxyName(Name name, int index) {
1403 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1404 if (index > 0) {
1405 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1406 }
1407 return proxyName;
1408 }
1409
1410 /** Proxy definitions for all free variables in given list, in reverse order.
1411 * @param pos The source code position of the definition.
1412 * @param freevars The free variables.
1413 * @param owner The class in which the definitions go.
1414 * @param additionalFlags Any additional flags
1415 */
1416 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1417 return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1418 }
1419
1420 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1421 long additionalFlags) {
1422 long flags = FINAL | SYNTHETIC | additionalFlags;
1423 List<JCVariableDecl> defs = List.nil();
1424 Set<Name> proxyNames = new HashSet<>();
1425 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1426 VarSymbol v = l.head;
1427 int index = 0;
1428 Name proxyName;
1429 do {
1430 proxyName = proxyName(v.name, index++);
1431 } while (!proxyNames.add(proxyName));
1432 VarSymbol proxy = new VarSymbol(
1433 flags, proxyName, v.erasure(types), owner) {
1434 @Override
1485 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1486 ClassSymbol c = owner.enclClass();
1487 boolean isMandated =
1488 // Anonymous constructors
1489 (owner.isConstructor() && owner.isAnonymous()) ||
1490 // Constructors of non-private inner member classes
1491 (owner.isConstructor() && c.isInner() &&
1492 !c.isPrivate() && !c.isStatic());
1493 long flags =
1494 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1495 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1496 owner.extraParams = owner.extraParams.prepend(outerThis);
1497 return makeOuterThisVarDecl(pos, outerThis);
1498 }
1499
1500 /** Definition for this$n field.
1501 * @param pos The source code position of the definition.
1502 * @param owner The class in which the definition goes.
1503 */
1504 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1505 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | (allowValueClasses && owner.isValueClass() ? STRICT : 0));
1506 return makeOuterThisVarDecl(pos, outerThis);
1507 }
1508
1509 /** Return a list of trees that load the free variables in given list,
1510 * in reverse order.
1511 * @param pos The source code position to be used for the trees.
1512 * @param freevars The list of free variables.
1513 */
1514 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1515 List<JCExpression> args = List.nil();
1516 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1517 args = args.prepend(loadFreevar(pos, l.head));
1518 return args;
1519 }
1520 //where
1521 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1522 return access(v, make.at(pos).Ident(v), null, false);
1523 }
1524
1525 /** Construct a tree simulating the expression {@code C.this}.
1825 }
1826
1827 /* ************************************************************************
1828 * Code for .class
1829 *************************************************************************/
1830
1831 /** Return the symbol of a class to contain a cache of
1832 * compiler-generated statics such as class$ and the
1833 * $assertionsDisabled flag. We create an anonymous nested class
1834 * (unless one already exists) and return its symbol. However,
1835 * for backward compatibility in 1.4 and earlier we use the
1836 * top-level class itself.
1837 */
1838 private ClassSymbol outerCacheClass() {
1839 ClassSymbol clazz = outermostClassDef.sym;
1840 Scope s = clazz.members();
1841 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1842 if (sym.kind == TYP &&
1843 sym.name == names.empty &&
1844 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1845 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1846 return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1847 }
1848
1849 /** Create an attributed tree of the form left.name(). */
1850 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1851 Assert.checkNonNull(left.type);
1852 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1853 TreeInfo.types(args));
1854 return make.App(make.Select(left, funcsym), args);
1855 }
1856
1857 /** The tree simulating a T.class expression.
1858 * @param clazz The tree identifying type T.
1859 */
1860 private JCExpression classOf(JCTree clazz) {
1861 return classOfType(clazz.type, clazz.pos());
1862 }
1863
1864 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1865 switch (type.getTag()) {
1866 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1878 VarSymbol sym = new VarSymbol(
1879 STATIC | PUBLIC | FINAL, names._class,
1880 syms.classType, type.tsym);
1881 return make_at(pos).Select(make.Type(type), sym);
1882 default:
1883 throw new AssertionError();
1884 }
1885 }
1886
1887 /* ************************************************************************
1888 * Code for enabling/disabling assertions.
1889 *************************************************************************/
1890
1891 private ClassSymbol assertionsDisabledClassCache;
1892
1893 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1894 */
1895 private ClassSymbol assertionsDisabledClass() {
1896 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1897
1898 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1899 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1900
1901 return assertionsDisabledClassCache;
1902 }
1903
1904 // This code is not particularly robust if the user has
1905 // previously declared a member named '$assertionsDisabled'.
1906 // The same faulty idiom also appears in the translation of
1907 // class literals above. We should report an error if a
1908 // previous declaration is not synthetic.
1909
1910 private JCExpression assertFlagTest(DiagnosticPosition pos) {
1911 // Outermost class may be either true class or an interface.
1912 ClassSymbol outermostClass = outermostClassDef.sym;
1913
1914 //only classes can hold a non-public field, look for a usable one:
1915 ClassSymbol container = !currentClass.isInterface() ? currentClass :
1916 assertionsDisabledClass();
1917
1918 VarSymbol assertDisabledSym =
1919 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2167 proxies = new HashMap<>(proxies);
2168 List<VarSymbol> prevOuterThisStack = outerThisStack;
2169
2170 // If this is an enum definition
2171 if ((tree.mods.flags & ENUM) != 0 &&
2172 (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2173 visitEnumDef(tree);
2174
2175 if ((tree.mods.flags & RECORD) != 0) {
2176 visitRecordDef(tree);
2177 }
2178
2179 // If this is a nested class, define a this$n field for
2180 // it and add to proxies.
2181 JCVariableDecl otdef = null;
2182 if (currentClass.hasOuterInstance())
2183 otdef = outerThisDef(tree.pos, currentClass);
2184
2185 // If this is a local class, define proxies for all its free variables.
2186 List<JCVariableDecl> fvdefs = freevarDefs(
2187 tree.pos, freevars(currentClass), currentClass, allowValueClasses && currentClass.isValueClass() ? STRICT : LOCAL_CAPTURE_FIELD);
2188
2189 // Recursively translate superclass, interfaces.
2190 tree.extending = translate(tree.extending);
2191 tree.implementing = translate(tree.implementing);
2192
2193 if (currentClass.isDirectlyOrIndirectlyLocal()) {
2194 ClassSymbol encl = currentClass.owner.enclClass();
2195 if (encl.trans_local == null) {
2196 encl.trans_local = List.nil();
2197 }
2198 encl.trans_local = encl.trans_local.prepend(currentClass);
2199 }
2200
2201 // Recursively translate members, taking into account that new members
2202 // might be created during the translation and prepended to the member
2203 // list `tree.defs'.
2204 List<JCTree> seen = List.nil();
2205 while (tree.defs != seen) {
2206 List<JCTree> unseen = tree.defs;
2207 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2748 if (added.nonEmpty()) {
2749 List<JCStatement> initializers = added.toList();
2750 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2751 }
2752
2753 // pop local variables from proxy stack
2754 proxies = prevProxies;
2755
2756 outerThisStack = prevOuterThisStack;
2757 } else {
2758 super.visitMethodDef(tree);
2759 }
2760 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2761 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2762 // lets find out if there is any field waiting to be initialized
2763 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2764 for (Symbol sym : currentClass.getEnclosedElements()) {
2765 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2766 fields.append((VarSymbol) sym);
2767 }
2768 ListBuffer<JCStatement> initializers = new ListBuffer<>();
2769 for (VarSymbol field: fields) {
2770 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2771 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2772 make.at(tree.pos);
2773 initializers.add(make.Exec(
2774 make.Assign(
2775 make.Select(make.This(field.owner.erasure(types)), field),
2776 make.Ident(param)).setType(field.erasure(types))));
2777 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2778 }
2779 }
2780 if (initializers.nonEmpty()) {
2781 if (allowValueClasses && (tree.sym.owner.isValueClass() || ((ClassSymbol)tree.sym.owner).isRecord())) {
2782 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2783 } else {
2784 tree.body.stats = tree.body.stats.appendList(initializers);
2785 }
2786 }
2787 }
2788 result = tree;
2789 }
2790
2791 public void visitTypeCast(JCTypeCast tree) {
2792 tree.clazz = translate(tree.clazz);
2793 if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2794 tree.expr = translate(tree.expr, tree.type);
2795 else
2796 tree.expr = translate(tree.expr);
2797 result = tree;
2798 }
2799
2800 /**
2801 * All the exactness checks between primitive types that require a run-time
2802 * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2803 * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2804 * {@code S} and {@code T} are primitive types and correspond to the runtime
2805 * action that will be executed to check whether a certain value (that is passed
2806 * as a parameter) can be converted to {@code T} without loss of information.
2990 Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2991 if (constructor != tree.constructor) {
2992 tree.args = tree.args.append(makeNull());
2993 tree.constructor = constructor;
2994 }
2995
2996 // If created class has an outer instance, and new is qualified, pass
2997 // qualifier as first argument. If new is not qualified, pass the
2998 // correct outer instance as first argument.
2999 if (c.hasOuterInstance()) {
3000 JCExpression thisArg;
3001 if (tree.encl != null) {
3002 thisArg = attr.makeNullCheck(translate(tree.encl));
3003 thisArg.type = tree.encl.type;
3004 } else if (c.isDirectlyOrIndirectlyLocal()) {
3005 // local class
3006 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
3007 } else {
3008 // nested class
3009 thisArg = makeOwnerThis(tree.pos(), c, false);
3010 if (currentMethodSym != null &&
3011 ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
3012 currentMethodSym.owner.isValueClass()) {
3013 // instance initializer in a value class
3014 Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
3015 if (outerThisSet == null) {
3016 outerThisSet = new HashSet<>();
3017 }
3018 outerThisSet.add(thisArg);
3019 initializerOuterThis.put(currentClass, outerThisSet);
3020 }
3021 }
3022 tree.args = tree.args.prepend(thisArg);
3023 }
3024 tree.encl = null;
3025
3026 // If we have an anonymous class, create its flat version, rather
3027 // than the class or interface following new.
3028 if (tree.def != null) {
3029 translate(tree.def);
3030
3031 tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3032 tree.def = null;
3033 } else {
3034 tree.clazz = access(c, tree.clazz, enclOp, false);
3035 }
3036 result = tree;
3037 }
3038
3039 // Simplify conditionals with known constant controlling expressions.
3040 // This allows us to avoid generating supporting declarations for
|