90 private final Log log;
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 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 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
138 Source source = Source.instance(context);
139 Preview preview = Preview.instance(context);
140 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
141 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
142 typePairToName = TypePairs.initialize(syms);
143 }
144
145 /** The currently enclosing class.
146 */
147 ClassSymbol currentClass;
148
149 /** A queue of all translated classes.
150 */
151 ListBuffer<JCTree> translated;
152
153 /** Environment for symbol lookup, set by translateTopLevelClass.
154 */
155 Env<AttrContext> attrEnv;
156
157 /** A hash table mapping syntax trees to their ending source positions.
158 */
159 EndPosTable endPosTable;
160
161 /* ************************************************************************
162 * Global mappings
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 navigator class for assembling a mapping from local class symbols
200 * to class definition trees.
201 * There is only one case; all other cases simply traverse down the tree.
202 */
203 class ClassMap extends TreeScanner {
204
205 /** All encountered class defs are entered into classdefs table.
206 */
207 public void visitClassDef(JCClassDecl tree) {
208 classdefs.put(tree.sym, tree);
209 super.visitClassDef(tree);
210 }
211 }
212 ClassMap classMap = new ClassMap();
213
214 /** Map a class symbol to its definition.
215 * @param c The class symbol of which we want to determine the definition.
216 */
217 JCClassDecl classDef(ClassSymbol c) {
218 // First lookup the class in the classdefs table.
757
758 /** Look up a method in a given scope.
759 */
760 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
761 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
762 }
763
764 /** Anon inner classes are used as access constructor tags.
765 * accessConstructorTag will use an existing anon class if one is available,
766 * and synthesize a class (with makeEmptyClass) if one is not available.
767 * However, there is a small possibility that an existing class will not
768 * be generated as expected if it is inside a conditional with a constant
769 * expression. If that is found to be the case, create an empty class tree here.
770 */
771 private void checkAccessConstructorTags() {
772 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
773 ClassSymbol c = l.head;
774 if (isTranslatedClassAvailable(c))
775 continue;
776 // Create class definition tree.
777 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
778 c.outermostClass(), c.flatname, false);
779 swapAccessConstructorTag(c, cdec.sym);
780 translated.append(cdec);
781 }
782 }
783 // where
784 private boolean isTranslatedClassAvailable(ClassSymbol c) {
785 for (JCTree tree: translated) {
786 if (tree.hasTag(CLASSDEF)
787 && ((JCClassDecl) tree).sym == c) {
788 return true;
789 }
790 }
791 return false;
792 }
793
794 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
795 for (MethodSymbol methodSymbol : accessConstrs.values()) {
796 Assert.check(methodSymbol.type.hasTag(METHOD));
797 MethodType oldMethodType =
1229 accessConstrs.put(constr, aconstr);
1230 accessed.append(constr);
1231 }
1232 return aconstr;
1233 } else {
1234 return constr;
1235 }
1236 }
1237
1238 /** Return an anonymous class nested in this toplevel class.
1239 */
1240 ClassSymbol accessConstructorTag() {
1241 ClassSymbol topClass = currentClass.outermostClass();
1242 ModuleSymbol topModle = topClass.packge().modle;
1243 for (int i = 1; ; i++) {
1244 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1245 target.syntheticNameChar() +
1246 i);
1247 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1248 if (ctag == null)
1249 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
1250 else if (!ctag.isAnonymous())
1251 continue;
1252 // keep a record of all tags, to verify that all are generated as required
1253 accessConstrTags = accessConstrTags.prepend(ctag);
1254 return ctag;
1255 }
1256 }
1257
1258 /** Add all required access methods for a private symbol to enclosing class.
1259 * @param sym The symbol.
1260 */
1261 void makeAccessible(Symbol sym) {
1262 JCClassDecl cdef = classDef(sym.owner.enclClass());
1263 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1264 if (sym.name == names.init) {
1265 cdef.defs = cdef.defs.prepend(
1266 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1267 } else {
1268 MethodSymbol[] accessors = accessSyms.get(sym);
1269 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1385
1386 /** A stack containing the this$n field of the currently translated
1387 * classes (if needed) in innermost first order.
1388 * Inside a constructor, proxies and any this$n symbol are duplicated
1389 * in an additional innermost scope, where they represent the constructor
1390 * parameters.
1391 */
1392 List<VarSymbol> outerThisStack;
1393
1394 /** The name of a free variable proxy.
1395 */
1396 Name proxyName(Name name, int index) {
1397 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1398 if (index > 0) {
1399 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1400 }
1401 return proxyName;
1402 }
1403
1404 /** Proxy definitions for all free variables in given list, in reverse order.
1405 * @param pos The source code position of the definition.
1406 * @param freevars The free variables.
1407 * @param owner The class in which the definitions go.
1408 */
1409 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1410 return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1411 }
1412
1413 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1414 long additionalFlags) {
1415 long flags = FINAL | SYNTHETIC | additionalFlags;
1416 List<JCVariableDecl> defs = List.nil();
1417 Set<Name> proxyNames = new HashSet<>();
1418 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1419 VarSymbol v = l.head;
1420 int index = 0;
1421 Name proxyName;
1422 do {
1423 proxyName = proxyName(v.name, index++);
1424 } while (!proxyNames.add(proxyName));
1425 VarSymbol proxy = new VarSymbol(
1426 flags, proxyName, v.erasure(types), owner) {
1427 @Override
1478 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1479 ClassSymbol c = owner.enclClass();
1480 boolean isMandated =
1481 // Anonymous constructors
1482 (owner.isConstructor() && owner.isAnonymous()) ||
1483 // Constructors of non-private inner member classes
1484 (owner.isConstructor() && c.isInner() &&
1485 !c.isPrivate() && !c.isStatic());
1486 long flags =
1487 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1488 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1489 owner.extraParams = owner.extraParams.prepend(outerThis);
1490 return makeOuterThisVarDecl(pos, outerThis);
1491 }
1492
1493 /** Definition for this$n field.
1494 * @param pos The source code position of the definition.
1495 * @param owner The class in which the definition goes.
1496 */
1497 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1498 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1499 return makeOuterThisVarDecl(pos, outerThis);
1500 }
1501
1502 /** Return a list of trees that load the free variables in given list,
1503 * in reverse order.
1504 * @param pos The source code position to be used for the trees.
1505 * @param freevars The list of free variables.
1506 */
1507 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1508 List<JCExpression> args = List.nil();
1509 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1510 args = args.prepend(loadFreevar(pos, l.head));
1511 return args;
1512 }
1513 //where
1514 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1515 return access(v, make.at(pos).Ident(v), null, false);
1516 }
1517
1518 /** Construct a tree simulating the expression {@code C.this}.
1809 }
1810
1811 /* ************************************************************************
1812 * Code for .class
1813 *************************************************************************/
1814
1815 /** Return the symbol of a class to contain a cache of
1816 * compiler-generated statics such as class$ and the
1817 * $assertionsDisabled flag. We create an anonymous nested class
1818 * (unless one already exists) and return its symbol. However,
1819 * for backward compatibility in 1.4 and earlier we use the
1820 * top-level class itself.
1821 */
1822 private ClassSymbol outerCacheClass() {
1823 ClassSymbol clazz = outermostClassDef.sym;
1824 Scope s = clazz.members();
1825 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1826 if (sym.kind == TYP &&
1827 sym.name == names.empty &&
1828 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1829 return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
1830 }
1831
1832 /** Create an attributed tree of the form left.name(). */
1833 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1834 Assert.checkNonNull(left.type);
1835 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1836 TreeInfo.types(args));
1837 return make.App(make.Select(left, funcsym), args);
1838 }
1839
1840 /** The tree simulating a T.class expression.
1841 * @param clazz The tree identifying type T.
1842 */
1843 private JCExpression classOf(JCTree clazz) {
1844 return classOfType(clazz.type, clazz.pos());
1845 }
1846
1847 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1848 switch (type.getTag()) {
1849 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1861 VarSymbol sym = new VarSymbol(
1862 STATIC | PUBLIC | FINAL, names._class,
1863 syms.classType, type.tsym);
1864 return make_at(pos).Select(make.Type(type), sym);
1865 default:
1866 throw new AssertionError();
1867 }
1868 }
1869
1870 /* ************************************************************************
1871 * Code for enabling/disabling assertions.
1872 *************************************************************************/
1873
1874 private ClassSymbol assertionsDisabledClassCache;
1875
1876 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1877 */
1878 private ClassSymbol assertionsDisabledClass() {
1879 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1880
1881 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
1882
1883 return assertionsDisabledClassCache;
1884 }
1885
1886 // This code is not particularly robust if the user has
1887 // previously declared a member named '$assertionsDisabled'.
1888 // The same faulty idiom also appears in the translation of
1889 // class literals above. We should report an error if a
1890 // previous declaration is not synthetic.
1891
1892 private JCExpression assertFlagTest(DiagnosticPosition pos) {
1893 // Outermost class may be either true class or an interface.
1894 ClassSymbol outermostClass = outermostClassDef.sym;
1895
1896 //only classes can hold a non-public field, look for a usable one:
1897 ClassSymbol container = !currentClass.isInterface() ? currentClass :
1898 assertionsDisabledClass();
1899
1900 VarSymbol assertDisabledSym =
1901 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2149 proxies = new HashMap<>(proxies);
2150 List<VarSymbol> prevOuterThisStack = outerThisStack;
2151
2152 // If this is an enum definition
2153 if ((tree.mods.flags & ENUM) != 0 &&
2154 (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2155 visitEnumDef(tree);
2156
2157 if ((tree.mods.flags & RECORD) != 0) {
2158 visitRecordDef(tree);
2159 }
2160
2161 // If this is a nested class, define a this$n field for
2162 // it and add to proxies.
2163 JCVariableDecl otdef = null;
2164 if (currentClass.hasOuterInstance())
2165 otdef = outerThisDef(tree.pos, currentClass);
2166
2167 // If this is a local class, define proxies for all its free variables.
2168 List<JCVariableDecl> fvdefs = freevarDefs(
2169 tree.pos, freevars(currentClass), currentClass);
2170
2171 // Recursively translate superclass, interfaces.
2172 tree.extending = translate(tree.extending);
2173 tree.implementing = translate(tree.implementing);
2174
2175 if (currentClass.isDirectlyOrIndirectlyLocal()) {
2176 ClassSymbol encl = currentClass.owner.enclClass();
2177 if (encl.trans_local == null) {
2178 encl.trans_local = List.nil();
2179 }
2180 encl.trans_local = encl.trans_local.prepend(currentClass);
2181 }
2182
2183 // Recursively translate members, taking into account that new members
2184 // might be created during the translation and prepended to the member
2185 // list `tree.defs'.
2186 List<JCTree> seen = List.nil();
2187 while (tree.defs != seen) {
2188 List<JCTree> unseen = tree.defs;
2189 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2723 if (added.nonEmpty()) {
2724 List<JCStatement> initializers = added.toList();
2725 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2726 }
2727
2728 // pop local variables from proxy stack
2729 proxies = prevProxies;
2730
2731 outerThisStack = prevOuterThisStack;
2732 } else {
2733 super.visitMethodDef(tree);
2734 }
2735 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2736 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2737 // lets find out if there is any field waiting to be initialized
2738 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2739 for (Symbol sym : currentClass.getEnclosedElements()) {
2740 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2741 fields.append((VarSymbol) sym);
2742 }
2743 for (VarSymbol field: fields) {
2744 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2745 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2746 make.at(tree.pos);
2747 tree.body.stats = tree.body.stats.append(
2748 make.Exec(
2749 make.Assign(
2750 make.Select(make.This(field.owner.erasure(types)), field),
2751 make.Ident(param)).setType(field.erasure(types))));
2752 // we don't need the flag at the field anymore
2753 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2754 }
2755 }
2756 }
2757 result = tree;
2758 }
2759
2760 public void visitTypeCast(JCTypeCast tree) {
2761 tree.clazz = translate(tree.clazz);
2762 if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2763 tree.expr = translate(tree.expr, tree.type);
2764 else
2765 tree.expr = translate(tree.expr);
2766 result = tree;
2767 }
2768
2769 /**
2770 * All the exactness checks between primitive types that require a run-time
2771 * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2772 * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2773 * {@code S} and {@code T} are primitive types and correspond to the runtime
2774 * action that will be executed to check whether a certain value (that is passed
2775 * as a parameter) can be converted to {@code T} without loss of information.
2951 Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2952 if (constructor != tree.constructor) {
2953 tree.args = tree.args.append(makeNull());
2954 tree.constructor = constructor;
2955 }
2956
2957 // If created class has an outer instance, and new is qualified, pass
2958 // qualifier as first argument. If new is not qualified, pass the
2959 // correct outer instance as first argument.
2960 if (c.hasOuterInstance()) {
2961 JCExpression thisArg;
2962 if (tree.encl != null) {
2963 thisArg = attr.makeNullCheck(translate(tree.encl));
2964 thisArg.type = tree.encl.type;
2965 } else if (c.isDirectlyOrIndirectlyLocal()) {
2966 // local class
2967 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2968 } else {
2969 // nested class
2970 thisArg = makeOwnerThis(tree.pos(), c, false);
2971 }
2972 tree.args = tree.args.prepend(thisArg);
2973 }
2974 tree.encl = null;
2975
2976 // If we have an anonymous class, create its flat version, rather
2977 // than the class or interface following new.
2978 if (tree.def != null) {
2979 translate(tree.def);
2980
2981 tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
2982 tree.def = null;
2983 } else {
2984 tree.clazz = access(c, tree.clazz, enclOp, false);
2985 }
2986 result = tree;
2987 }
2988
2989 // Simplify conditionals with known constant controlling expressions.
2990 // This allows us to avoid generating supporting declarations for
|
90 private final Log log;
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 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 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 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
145 Feature.VALUE_CLASSES.allowedInSource(source);
146 }
147
148 /** The currently enclosing class.
149 */
150 ClassSymbol currentClass;
151
152 /** A queue of all translated classes.
153 */
154 ListBuffer<JCTree> translated;
155
156 /** Environment for symbol lookup, set by translateTopLevelClass.
157 */
158 Env<AttrContext> attrEnv;
159
160 /** 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 hash table mapping local classes to a set of outer this fields
203 */
204 public Map<ClassSymbol, Set<JCExpression>> initializerOuterThis = new WeakHashMap<>();
205
206 /** A navigator class for assembling a mapping from local class symbols
207 * to class definition trees.
208 * There is only one case; all other cases simply traverse down the tree.
209 */
210 class ClassMap extends TreeScanner {
211
212 /** All encountered class defs are entered into classdefs table.
213 */
214 public void visitClassDef(JCClassDecl tree) {
215 classdefs.put(tree.sym, tree);
216 super.visitClassDef(tree);
217 }
218 }
219 ClassMap classMap = new ClassMap();
220
221 /** Map a class symbol to its definition.
222 * @param c The class symbol of which we want to determine the definition.
223 */
224 JCClassDecl classDef(ClassSymbol c) {
225 // First lookup the class in the classdefs table.
764
765 /** Look up a method in a given scope.
766 */
767 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
768 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
769 }
770
771 /** Anon inner classes are used as access constructor tags.
772 * accessConstructorTag will use an existing anon class if one is available,
773 * and synthesize a class (with makeEmptyClass) if one is not available.
774 * However, there is a small possibility that an existing class will not
775 * be generated as expected if it is inside a conditional with a constant
776 * expression. If that is found to be the case, create an empty class tree here.
777 */
778 private void checkAccessConstructorTags() {
779 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
780 ClassSymbol c = l.head;
781 if (isTranslatedClassAvailable(c))
782 continue;
783 // Create class definition tree.
784 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
785 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
786 c.outermostClass(), c.flatname, false);
787 swapAccessConstructorTag(c, cdec.sym);
788 translated.append(cdec);
789 }
790 }
791 // where
792 private boolean isTranslatedClassAvailable(ClassSymbol c) {
793 for (JCTree tree: translated) {
794 if (tree.hasTag(CLASSDEF)
795 && ((JCClassDecl) tree).sym == c) {
796 return true;
797 }
798 }
799 return false;
800 }
801
802 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
803 for (MethodSymbol methodSymbol : accessConstrs.values()) {
804 Assert.check(methodSymbol.type.hasTag(METHOD));
805 MethodType oldMethodType =
1237 accessConstrs.put(constr, aconstr);
1238 accessed.append(constr);
1239 }
1240 return aconstr;
1241 } else {
1242 return constr;
1243 }
1244 }
1245
1246 /** Return an anonymous class nested in this toplevel class.
1247 */
1248 ClassSymbol accessConstructorTag() {
1249 ClassSymbol topClass = currentClass.outermostClass();
1250 ModuleSymbol topModle = topClass.packge().modle;
1251 for (int i = 1; ; i++) {
1252 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1253 target.syntheticNameChar() +
1254 i);
1255 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1256 if (ctag == null)
1257 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1258 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1259 else if (!ctag.isAnonymous())
1260 continue;
1261 // keep a record of all tags, to verify that all are generated as required
1262 accessConstrTags = accessConstrTags.prepend(ctag);
1263 return ctag;
1264 }
1265 }
1266
1267 /** Add all required access methods for a private symbol to enclosing class.
1268 * @param sym The symbol.
1269 */
1270 void makeAccessible(Symbol sym) {
1271 JCClassDecl cdef = classDef(sym.owner.enclClass());
1272 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1273 if (sym.name == names.init) {
1274 cdef.defs = cdef.defs.prepend(
1275 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1276 } else {
1277 MethodSymbol[] accessors = accessSyms.get(sym);
1278 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1394
1395 /** A stack containing the this$n field of the currently translated
1396 * classes (if needed) in innermost first order.
1397 * Inside a constructor, proxies and any this$n symbol are duplicated
1398 * in an additional innermost scope, where they represent the constructor
1399 * parameters.
1400 */
1401 List<VarSymbol> outerThisStack;
1402
1403 /** The name of a free variable proxy.
1404 */
1405 Name proxyName(Name name, int index) {
1406 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1407 if (index > 0) {
1408 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1409 }
1410 return proxyName;
1411 }
1412
1413 /** Proxy definitions for all free variables in given list, in reverse order.
1414 * @param pos The source code position of the definition.
1415 * @param freevars The free variables.
1416 * @param owner The class in which the definitions go.
1417 * @param additionalFlags Any additional flags
1418 */
1419 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1420 return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1421 }
1422
1423 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1424 long additionalFlags) {
1425 long flags = FINAL | SYNTHETIC | additionalFlags;
1426 List<JCVariableDecl> defs = List.nil();
1427 Set<Name> proxyNames = new HashSet<>();
1428 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1429 VarSymbol v = l.head;
1430 int index = 0;
1431 Name proxyName;
1432 do {
1433 proxyName = proxyName(v.name, index++);
1434 } while (!proxyNames.add(proxyName));
1435 VarSymbol proxy = new VarSymbol(
1436 flags, proxyName, v.erasure(types), owner) {
1437 @Override
1488 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1489 ClassSymbol c = owner.enclClass();
1490 boolean isMandated =
1491 // Anonymous constructors
1492 (owner.isConstructor() && owner.isAnonymous()) ||
1493 // Constructors of non-private inner member classes
1494 (owner.isConstructor() && c.isInner() &&
1495 !c.isPrivate() && !c.isStatic());
1496 long flags =
1497 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1498 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1499 owner.extraParams = owner.extraParams.prepend(outerThis);
1500 return makeOuterThisVarDecl(pos, outerThis);
1501 }
1502
1503 /** Definition for this$n field.
1504 * @param pos The source code position of the definition.
1505 * @param owner The class in which the definition goes.
1506 */
1507 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1508 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | (allowValueClasses && owner.isValueClass() ? STRICT : 0));
1509 return makeOuterThisVarDecl(pos, outerThis);
1510 }
1511
1512 /** Return a list of trees that load the free variables in given list,
1513 * in reverse order.
1514 * @param pos The source code position to be used for the trees.
1515 * @param freevars The list of free variables.
1516 */
1517 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1518 List<JCExpression> args = List.nil();
1519 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1520 args = args.prepend(loadFreevar(pos, l.head));
1521 return args;
1522 }
1523 //where
1524 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1525 return access(v, make.at(pos).Ident(v), null, false);
1526 }
1527
1528 /** Construct a tree simulating the expression {@code C.this}.
1819 }
1820
1821 /* ************************************************************************
1822 * Code for .class
1823 *************************************************************************/
1824
1825 /** Return the symbol of a class to contain a cache of
1826 * compiler-generated statics such as class$ and the
1827 * $assertionsDisabled flag. We create an anonymous nested class
1828 * (unless one already exists) and return its symbol. However,
1829 * for backward compatibility in 1.4 and earlier we use the
1830 * top-level class itself.
1831 */
1832 private ClassSymbol outerCacheClass() {
1833 ClassSymbol clazz = outermostClassDef.sym;
1834 Scope s = clazz.members();
1835 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1836 if (sym.kind == TYP &&
1837 sym.name == names.empty &&
1838 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1839 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1840 return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, 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 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1893 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, 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, allowValueClasses && currentClass.isValueClass() ? STRICT : LOCAL_CAPTURE_FIELD);
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) {
2735 if (added.nonEmpty()) {
2736 List<JCStatement> initializers = added.toList();
2737 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2738 }
2739
2740 // pop local variables from proxy stack
2741 proxies = prevProxies;
2742
2743 outerThisStack = prevOuterThisStack;
2744 } else {
2745 super.visitMethodDef(tree);
2746 }
2747 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2748 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2749 // lets find out if there is any field waiting to be initialized
2750 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2751 for (Symbol sym : currentClass.getEnclosedElements()) {
2752 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2753 fields.append((VarSymbol) sym);
2754 }
2755 ListBuffer<JCStatement> initializers = new ListBuffer<>();
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 initializers.add(make.Exec(
2761 make.Assign(
2762 make.Select(make.This(field.owner.erasure(types)), field),
2763 make.Ident(param)).setType(field.erasure(types))));
2764 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2765 }
2766 }
2767 if (initializers.nonEmpty()) {
2768 if (tree.sym.owner.isValueClass()) {
2769 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2770 } else {
2771 tree.body.stats = tree.body.stats.appendList(initializers);
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.
2969 Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2970 if (constructor != tree.constructor) {
2971 tree.args = tree.args.append(makeNull());
2972 tree.constructor = constructor;
2973 }
2974
2975 // If created class has an outer instance, and new is qualified, pass
2976 // qualifier as first argument. If new is not qualified, pass the
2977 // correct outer instance as first argument.
2978 if (c.hasOuterInstance()) {
2979 JCExpression thisArg;
2980 if (tree.encl != null) {
2981 thisArg = attr.makeNullCheck(translate(tree.encl));
2982 thisArg.type = tree.encl.type;
2983 } else if (c.isDirectlyOrIndirectlyLocal()) {
2984 // local class
2985 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2986 } else {
2987 // nested class
2988 thisArg = makeOwnerThis(tree.pos(), c, false);
2989 if (currentMethodSym != null &&
2990 ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
2991 currentMethodSym.owner.isValueClass()) {
2992 // instance initializer in a value class
2993 Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
2994 if (outerThisSet == null) {
2995 outerThisSet = new HashSet<>();
2996 }
2997 outerThisSet.add(thisArg);
2998 initializerOuterThis.put(currentClass, outerThisSet);
2999 }
3000 }
3001 tree.args = tree.args.prepend(thisArg);
3002 }
3003 tree.encl = null;
3004
3005 // If we have an anonymous class, create its flat version, rather
3006 // than the class or interface following new.
3007 if (tree.def != null) {
3008 translate(tree.def);
3009
3010 tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3011 tree.def = null;
3012 } else {
3013 tree.clazz = access(c, tree.clazz, enclOp, false);
3014 }
3015 result = tree;
3016 }
3017
3018 // Simplify conditionals with known constant controlling expressions.
3019 // This allows us to avoid generating supporting declarations for
|