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