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