86 private final Log log;
87 private final Symtab syms;
88 private final Resolve rs;
89 private final Operators operators;
90 private final Check chk;
91 private final Attr attr;
92 private TreeMaker make;
93 private DiagnosticPosition make_pos;
94 private final ConstFold cfolder;
95 private final Target target;
96 private final TypeEnvs typeEnvs;
97 private final Name dollarAssertionsDisabled;
98 private final Types types;
99 private final TransTypes transTypes;
100 private final boolean debugLower;
101 private final boolean disableProtectedAccessors; // experimental
102 private final PkgInfo pkginfoOpt;
103 private final boolean optimizeOuterThis;
104 private final boolean useMatchException;
105 private final HashMap<TypePairs, String> typePairToName;
106
107 @SuppressWarnings("this-escape")
108 protected Lower(Context context) {
109 context.put(lowerKey, this);
110 names = Names.instance(context);
111 log = Log.instance(context);
112 syms = Symtab.instance(context);
113 rs = Resolve.instance(context);
114 operators = Operators.instance(context);
115 chk = Check.instance(context);
116 attr = Attr.instance(context);
117 make = TreeMaker.instance(context);
118 cfolder = ConstFold.instance(context);
119 target = Target.instance(context);
120 typeEnvs = TypeEnvs.instance(context);
121 dollarAssertionsDisabled = names.
122 fromString(target.syntheticNameChar() + "assertionsDisabled");
123
124 types = Types.instance(context);
125 transTypes = TransTypes.instance(context);
126 Options options = Options.instance(context);
127 debugLower = options.isSet("debuglower");
128 pkginfoOpt = PkgInfo.get(options);
129 optimizeOuterThis =
130 target.optimizeOuterThis() ||
131 options.getBoolean("optimizeOuterThis", false);
132 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
133 Source source = Source.instance(context);
134 Preview preview = Preview.instance(context);
135 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
136 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
137 typePairToName = TypePairs.initialize(syms);
138 }
139
140 /** The currently enclosing class.
141 */
142 ClassSymbol currentClass;
143
144 /** A queue of all translated classes.
145 */
146 ListBuffer<JCTree> translated;
147
148 /** Environment for symbol lookup, set by translateTopLevelClass.
149 */
150 Env<AttrContext> attrEnv;
151
152 /** A hash table mapping syntax trees to their ending source positions.
153 */
154 EndPosTable endPosTable;
155
156 /**************************************************************************
157 * Global mappings
175 JCMethodDecl currentMethodDef;
176
177 /** The current method symbol.
178 */
179 MethodSymbol currentMethodSym;
180
181 /** The currently enclosing outermost class definition.
182 */
183 JCClassDecl outermostClassDef;
184
185 /** The currently enclosing outermost member definition.
186 */
187 JCTree outermostMemberDef;
188
189 /** A map from local variable symbols to their translation (as per LambdaToMethod).
190 * This is required when a capturing local class is created from a lambda (in which
191 * case the captured symbols should be replaced with the translated lambda symbols).
192 */
193 Map<Symbol, Symbol> lambdaTranslationMap = null;
194
195 /** A navigator class for assembling a mapping from local class symbols
196 * to class definition trees.
197 * There is only one case; all other cases simply traverse down the tree.
198 */
199 class ClassMap extends TreeScanner {
200
201 /** All encountered class defs are entered into classdefs table.
202 */
203 public void visitClassDef(JCClassDecl tree) {
204 classdefs.put(tree.sym, tree);
205 super.visitClassDef(tree);
206 }
207 }
208 ClassMap classMap = new ClassMap();
209
210 /** Map a class symbol to its definition.
211 * @param c The class symbol of which we want to determine the definition.
212 */
213 JCClassDecl classDef(ClassSymbol c) {
214 // First lookup the class in the classdefs table.
891
892 /** Look up a method in a given scope.
893 */
894 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
895 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
896 }
897
898 /** Anon inner classes are used as access constructor tags.
899 * accessConstructorTag will use an existing anon class if one is available,
900 * and synthesize a class (with makeEmptyClass) if one is not available.
901 * However, there is a small possibility that an existing class will not
902 * be generated as expected if it is inside a conditional with a constant
903 * expression. If that is found to be the case, create an empty class tree here.
904 */
905 private void checkAccessConstructorTags() {
906 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
907 ClassSymbol c = l.head;
908 if (isTranslatedClassAvailable(c))
909 continue;
910 // Create class definition tree.
911 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
912 c.outermostClass(), c.flatname, false);
913 swapAccessConstructorTag(c, cdec.sym);
914 translated.append(cdec);
915 }
916 }
917 // where
918 private boolean isTranslatedClassAvailable(ClassSymbol c) {
919 for (JCTree tree: translated) {
920 if (tree.hasTag(CLASSDEF)
921 && ((JCClassDecl) tree).sym == c) {
922 return true;
923 }
924 }
925 return false;
926 }
927
928 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
929 for (MethodSymbol methodSymbol : accessConstrs.values()) {
930 Assert.check(methodSymbol.type.hasTag(METHOD));
931 MethodType oldMethodType =
1375 accessConstrs.put(constr, aconstr);
1376 accessed.append(constr);
1377 }
1378 return aconstr;
1379 } else {
1380 return constr;
1381 }
1382 }
1383
1384 /** Return an anonymous class nested in this toplevel class.
1385 */
1386 ClassSymbol accessConstructorTag() {
1387 ClassSymbol topClass = currentClass.outermostClass();
1388 ModuleSymbol topModle = topClass.packge().modle;
1389 for (int i = 1; ; i++) {
1390 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1391 target.syntheticNameChar() +
1392 i);
1393 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1394 if (ctag == null)
1395 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
1396 else if (!ctag.isAnonymous())
1397 continue;
1398 // keep a record of all tags, to verify that all are generated as required
1399 accessConstrTags = accessConstrTags.prepend(ctag);
1400 return ctag;
1401 }
1402 }
1403
1404 /** Add all required access methods for a private symbol to enclosing class.
1405 * @param sym The symbol.
1406 */
1407 void makeAccessible(Symbol sym) {
1408 JCClassDecl cdef = classDef(sym.owner.enclClass());
1409 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1410 if (sym.name == names.init) {
1411 cdef.defs = cdef.defs.prepend(
1412 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1413 } else {
1414 MethodSymbol[] accessors = accessSyms.get(sym);
1415 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1531
1532 /** A stack containing the this$n field of the currently translated
1533 * classes (if needed) in innermost first order.
1534 * Inside a constructor, proxies and any this$n symbol are duplicated
1535 * in an additional innermost scope, where they represent the constructor
1536 * parameters.
1537 */
1538 List<VarSymbol> outerThisStack;
1539
1540 /** The name of a free variable proxy.
1541 */
1542 Name proxyName(Name name, int index) {
1543 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1544 if (index > 0) {
1545 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1546 }
1547 return proxyName;
1548 }
1549
1550 /** Proxy definitions for all free variables in given list, in reverse order.
1551 * @param pos The source code position of the definition.
1552 * @param freevars The free variables.
1553 * @param owner The class in which the definitions go.
1554 */
1555 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1556 return freevarDefs(pos, freevars, owner, 0);
1557 }
1558
1559 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1560 long additionalFlags) {
1561 long flags = FINAL | SYNTHETIC | additionalFlags;
1562 List<JCVariableDecl> defs = List.nil();
1563 Set<Name> proxyNames = new HashSet<>();
1564 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1565 VarSymbol v = l.head;
1566 int index = 0;
1567 Name proxyName;
1568 do {
1569 proxyName = proxyName(v.name, index++);
1570 } while (!proxyNames.add(proxyName));
1571 VarSymbol proxy = new VarSymbol(
1572 flags, proxyName, v.erasure(types), owner);
1573 proxies.put(v, proxy);
1574 JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1575 vd.vartype = access(vd.vartype);
1576 defs = defs.prepend(vd);
1577 }
1578 return defs;
1619 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1620 ClassSymbol c = owner.enclClass();
1621 boolean isMandated =
1622 // Anonymous constructors
1623 (owner.isConstructor() && owner.isAnonymous()) ||
1624 // Constructors of non-private inner member classes
1625 (owner.isConstructor() && c.isInner() &&
1626 !c.isPrivate() && !c.isStatic());
1627 long flags =
1628 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1629 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1630 owner.extraParams = owner.extraParams.prepend(outerThis);
1631 return makeOuterThisVarDecl(pos, outerThis);
1632 }
1633
1634 /** Definition for this$n field.
1635 * @param pos The source code position of the definition.
1636 * @param owner The class in which the definition goes.
1637 */
1638 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1639 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1640 return makeOuterThisVarDecl(pos, outerThis);
1641 }
1642
1643 /** Return a list of trees that load the free variables in given list,
1644 * in reverse order.
1645 * @param pos The source code position to be used for the trees.
1646 * @param freevars The list of free variables.
1647 */
1648 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1649 List<JCExpression> args = List.nil();
1650 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1651 args = args.prepend(loadFreevar(pos, l.head));
1652 return args;
1653 }
1654 //where
1655 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1656 return access(v, make.at(pos).Ident(v), null, false);
1657 }
1658
1659 /** Construct a tree simulating the expression {@code C.this}.
1826 // create resource.close() method invocation
1827 JCExpression resourceClose = makeCall(resource,
1828 names.close,
1829 List.nil());
1830 return make.Exec(resourceClose);
1831 }
1832
1833 private JCExpression makeNonNullCheck(JCExpression expression) {
1834 return makeBinary(NE, expression, makeNull());
1835 }
1836
1837 /** Construct a tree that represents the outer instance
1838 * {@code C.this}. Never pick the current `this'.
1839 * @param pos The source code position to be used for the tree.
1840 * @param c The qualifier class.
1841 */
1842 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1843 List<VarSymbol> ots = outerThisStack;
1844 if (ots.isEmpty()) {
1845 log.error(pos, Errors.NoEnclInstanceOfTypeInScope(c));
1846 Assert.error();
1847 return makeNull();
1848 }
1849 VarSymbol ot = ots.head;
1850 JCExpression tree = access(make.at(pos).Ident(ot));
1851 ot.flags_field &= ~NOOUTERTHIS;
1852 TypeSymbol otc = ot.type.tsym;
1853 while (otc != c) {
1854 do {
1855 ots = ots.tail;
1856 if (ots.isEmpty()) {
1857 log.error(pos, Errors.NoEnclInstanceOfTypeInScope(c));
1858 Assert.error(); // should have been caught in Attr
1859 return tree;
1860 }
1861 ot = ots.head;
1862 } while (ot.owner != otc);
1863 if (otc.owner.kind != PCK && !otc.hasOuterInstance()) {
1864 log.error(pos, Errors.NoEnclInstanceOfTypeInScope(c));
1865 Assert.error(); // should have been caught in Attr
1866 return makeNull();
1952 }
1953
1954 /**************************************************************************
1955 * Code for .class
1956 *************************************************************************/
1957
1958 /** Return the symbol of a class to contain a cache of
1959 * compiler-generated statics such as class$ and the
1960 * $assertionsDisabled flag. We create an anonymous nested class
1961 * (unless one already exists) and return its symbol. However,
1962 * for backward compatibility in 1.4 and earlier we use the
1963 * top-level class itself.
1964 */
1965 private ClassSymbol outerCacheClass() {
1966 ClassSymbol clazz = outermostClassDef.sym;
1967 Scope s = clazz.members();
1968 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1969 if (sym.kind == TYP &&
1970 sym.name == names.empty &&
1971 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1972 return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
1973 }
1974
1975 /** Create an attributed tree of the form left.name(). */
1976 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1977 Assert.checkNonNull(left.type);
1978 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1979 TreeInfo.types(args));
1980 return make.App(make.Select(left, funcsym), args);
1981 }
1982
1983 /** The tree simulating a T.class expression.
1984 * @param clazz The tree identifying type T.
1985 */
1986 private JCExpression classOf(JCTree clazz) {
1987 return classOfType(clazz.type, clazz.pos());
1988 }
1989
1990 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1991 switch (type.getTag()) {
1992 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2004 VarSymbol sym = new VarSymbol(
2005 STATIC | PUBLIC | FINAL, names._class,
2006 syms.classType, type.tsym);
2007 return make_at(pos).Select(make.Type(type), sym);
2008 default:
2009 throw new AssertionError();
2010 }
2011 }
2012
2013 /**************************************************************************
2014 * Code for enabling/disabling assertions.
2015 *************************************************************************/
2016
2017 private ClassSymbol assertionsDisabledClassCache;
2018
2019 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
2020 */
2021 private ClassSymbol assertionsDisabledClass() {
2022 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
2023
2024 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
2025
2026 return assertionsDisabledClassCache;
2027 }
2028
2029 // This code is not particularly robust if the user has
2030 // previously declared a member named '$assertionsDisabled'.
2031 // The same faulty idiom also appears in the translation of
2032 // class literals above. We should report an error if a
2033 // previous declaration is not synthetic.
2034
2035 private JCExpression assertFlagTest(DiagnosticPosition pos) {
2036 // Outermost class may be either true class or an interface.
2037 ClassSymbol outermostClass = outermostClassDef.sym;
2038
2039 //only classes can hold a non-public field, look for a usable one:
2040 ClassSymbol container = !currentClass.isInterface() ? currentClass :
2041 assertionsDisabledClass();
2042
2043 VarSymbol assertDisabledSym =
2044 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2292 proxies = new HashMap<>(proxies);
2293 List<VarSymbol> prevOuterThisStack = outerThisStack;
2294
2295 // If this is an enum definition
2296 if ((tree.mods.flags & ENUM) != 0 &&
2297 (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2298 visitEnumDef(tree);
2299
2300 if ((tree.mods.flags & RECORD) != 0) {
2301 visitRecordDef(tree);
2302 }
2303
2304 // If this is a nested class, define a this$n field for
2305 // it and add to proxies.
2306 JCVariableDecl otdef = null;
2307 if (currentClass.hasOuterInstance())
2308 otdef = outerThisDef(tree.pos, currentClass);
2309
2310 // If this is a local class, define proxies for all its free variables.
2311 List<JCVariableDecl> fvdefs = freevarDefs(
2312 tree.pos, freevars(currentClass), currentClass);
2313
2314 // Recursively translate superclass, interfaces.
2315 tree.extending = translate(tree.extending);
2316 tree.implementing = translate(tree.implementing);
2317
2318 if (currentClass.isDirectlyOrIndirectlyLocal()) {
2319 ClassSymbol encl = currentClass.owner.enclClass();
2320 if (encl.trans_local == null) {
2321 encl.trans_local = List.nil();
2322 }
2323 encl.trans_local = encl.trans_local.prepend(currentClass);
2324 }
2325
2326 // Recursively translate members, taking into account that new members
2327 // might be created during the translation and prepended to the member
2328 // list `tree.defs'.
2329 List<JCTree> seen = List.nil();
2330 while (tree.defs != seen) {
2331 List<JCTree> unseen = tree.defs;
2332 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2869 } else {
2870 Map<Symbol, Symbol> prevLambdaTranslationMap =
2871 lambdaTranslationMap;
2872 try {
2873 lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 &&
2874 tree.sym.name.startsWith(names.lambda) ?
2875 makeTranslationMap(tree) : null;
2876 super.visitMethodDef(tree);
2877 } finally {
2878 lambdaTranslationMap = prevLambdaTranslationMap;
2879 }
2880 }
2881 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2882 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2883 // lets find out if there is any field waiting to be initialized
2884 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2885 for (Symbol sym : currentClass.getEnclosedElements()) {
2886 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2887 fields.append((VarSymbol) sym);
2888 }
2889 for (VarSymbol field: fields) {
2890 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2891 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2892 make.at(tree.pos);
2893 tree.body.stats = tree.body.stats.append(
2894 make.Exec(
2895 make.Assign(
2896 make.Select(make.This(field.owner.erasure(types)), field),
2897 make.Ident(param)).setType(field.erasure(types))));
2898 // we don't need the flag at the field anymore
2899 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2900 }
2901 }
2902 }
2903 result = tree;
2904 }
2905 //where
2906 private Map<Symbol, Symbol> makeTranslationMap(JCMethodDecl tree) {
2907 Map<Symbol, Symbol> translationMap = new HashMap<>();
2908 for (JCVariableDecl vd : tree.params) {
2909 Symbol p = vd.sym;
2910 if (p != p.baseSymbol()) {
2911 translationMap.put(p.baseSymbol(), p);
2912 }
2913 }
2914 return translationMap;
2915 }
2916
2917 public void visitTypeCast(JCTypeCast tree) {
2918 tree.clazz = translate(tree.clazz);
2919 if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2920 tree.expr = translate(tree.expr, tree.type);
2921 else
3115 Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
3116 if (constructor != tree.constructor) {
3117 tree.args = tree.args.append(makeNull());
3118 tree.constructor = constructor;
3119 }
3120
3121 // If created class has an outer instance, and new is qualified, pass
3122 // qualifier as first argument. If new is not qualified, pass the
3123 // correct outer instance as first argument.
3124 if (c.hasOuterInstance()) {
3125 JCExpression thisArg;
3126 if (tree.encl != null) {
3127 thisArg = attr.makeNullCheck(translate(tree.encl));
3128 thisArg.type = tree.encl.type;
3129 } else if (c.isDirectlyOrIndirectlyLocal()) {
3130 // local class
3131 thisArg = makeThis(tree.pos(), c.type.getEnclosingType().tsym);
3132 } else {
3133 // nested class
3134 thisArg = makeOwnerThis(tree.pos(), c, false);
3135 }
3136 tree.args = tree.args.prepend(thisArg);
3137 }
3138 tree.encl = null;
3139
3140 // If we have an anonymous class, create its flat version, rather
3141 // than the class or interface following new.
3142 if (tree.def != null) {
3143 Map<Symbol, Symbol> prevLambdaTranslationMap = lambdaTranslationMap;
3144 try {
3145 lambdaTranslationMap = null;
3146 translate(tree.def);
3147 } finally {
3148 lambdaTranslationMap = prevLambdaTranslationMap;
3149 }
3150
3151 tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3152 tree.def = null;
3153 } else {
3154 tree.clazz = access(c, tree.clazz, enclOp, false);
|
86 private final Log log;
87 private final Symtab syms;
88 private final Resolve rs;
89 private final Operators operators;
90 private final Check chk;
91 private final Attr attr;
92 private TreeMaker make;
93 private DiagnosticPosition make_pos;
94 private final ConstFold cfolder;
95 private final Target target;
96 private final TypeEnvs typeEnvs;
97 private final Name dollarAssertionsDisabled;
98 private final Types types;
99 private final TransTypes transTypes;
100 private final boolean debugLower;
101 private final boolean disableProtectedAccessors; // experimental
102 private final PkgInfo pkginfoOpt;
103 private final boolean optimizeOuterThis;
104 private final boolean useMatchException;
105 private final HashMap<TypePairs, String> typePairToName;
106 private final boolean allowValueClasses;
107
108 @SuppressWarnings("this-escape")
109 protected Lower(Context context) {
110 context.put(lowerKey, this);
111 names = Names.instance(context);
112 log = Log.instance(context);
113 syms = Symtab.instance(context);
114 rs = Resolve.instance(context);
115 operators = Operators.instance(context);
116 chk = Check.instance(context);
117 attr = Attr.instance(context);
118 make = TreeMaker.instance(context);
119 cfolder = ConstFold.instance(context);
120 target = Target.instance(context);
121 typeEnvs = TypeEnvs.instance(context);
122 dollarAssertionsDisabled = names.
123 fromString(target.syntheticNameChar() + "assertionsDisabled");
124
125 types = Types.instance(context);
126 transTypes = TransTypes.instance(context);
127 Options options = Options.instance(context);
128 debugLower = options.isSet("debuglower");
129 pkginfoOpt = PkgInfo.get(options);
130 optimizeOuterThis =
131 target.optimizeOuterThis() ||
132 options.getBoolean("optimizeOuterThis", false);
133 disableProtectedAccessors = options.isSet("disableProtectedAccessors");
134 Source source = Source.instance(context);
135 Preview preview = Preview.instance(context);
136 useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
137 (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
138 typePairToName = TypePairs.initialize(syms);
139 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
140 Feature.VALUE_CLASSES.allowedInSource(source);
141 }
142
143 /** The currently enclosing class.
144 */
145 ClassSymbol currentClass;
146
147 /** A queue of all translated classes.
148 */
149 ListBuffer<JCTree> translated;
150
151 /** Environment for symbol lookup, set by translateTopLevelClass.
152 */
153 Env<AttrContext> attrEnv;
154
155 /** A hash table mapping syntax trees to their ending source positions.
156 */
157 EndPosTable endPosTable;
158
159 /**************************************************************************
160 * Global mappings
178 JCMethodDecl currentMethodDef;
179
180 /** The current method symbol.
181 */
182 MethodSymbol currentMethodSym;
183
184 /** The currently enclosing outermost class definition.
185 */
186 JCClassDecl outermostClassDef;
187
188 /** The currently enclosing outermost member definition.
189 */
190 JCTree outermostMemberDef;
191
192 /** A map from local variable symbols to their translation (as per LambdaToMethod).
193 * This is required when a capturing local class is created from a lambda (in which
194 * case the captured symbols should be replaced with the translated lambda symbols).
195 */
196 Map<Symbol, Symbol> lambdaTranslationMap = null;
197
198 /** A hash table mapping local classes to a set of outer this fields
199 */
200 public Map<ClassSymbol, Set<JCExpression>> initializerOuterThis = new WeakHashMap<>();
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.
898
899 /** Look up a method in a given scope.
900 */
901 private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
902 return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
903 }
904
905 /** Anon inner classes are used as access constructor tags.
906 * accessConstructorTag will use an existing anon class if one is available,
907 * and synthesize a class (with makeEmptyClass) if one is not available.
908 * However, there is a small possibility that an existing class will not
909 * be generated as expected if it is inside a conditional with a constant
910 * expression. If that is found to be the case, create an empty class tree here.
911 */
912 private void checkAccessConstructorTags() {
913 for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
914 ClassSymbol c = l.head;
915 if (isTranslatedClassAvailable(c))
916 continue;
917 // Create class definition tree.
918 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
919 JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
920 c.outermostClass(), c.flatname, false);
921 swapAccessConstructorTag(c, cdec.sym);
922 translated.append(cdec);
923 }
924 }
925 // where
926 private boolean isTranslatedClassAvailable(ClassSymbol c) {
927 for (JCTree tree: translated) {
928 if (tree.hasTag(CLASSDEF)
929 && ((JCClassDecl) tree).sym == c) {
930 return true;
931 }
932 }
933 return false;
934 }
935
936 void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
937 for (MethodSymbol methodSymbol : accessConstrs.values()) {
938 Assert.check(methodSymbol.type.hasTag(METHOD));
939 MethodType oldMethodType =
1383 accessConstrs.put(constr, aconstr);
1384 accessed.append(constr);
1385 }
1386 return aconstr;
1387 } else {
1388 return constr;
1389 }
1390 }
1391
1392 /** Return an anonymous class nested in this toplevel class.
1393 */
1394 ClassSymbol accessConstructorTag() {
1395 ClassSymbol topClass = currentClass.outermostClass();
1396 ModuleSymbol topModle = topClass.packge().modle;
1397 for (int i = 1; ; i++) {
1398 Name flatname = names.fromString("" + topClass.getQualifiedName() +
1399 target.syntheticNameChar() +
1400 i);
1401 ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1402 if (ctag == null)
1403 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1404 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1405 else if (!ctag.isAnonymous())
1406 continue;
1407 // keep a record of all tags, to verify that all are generated as required
1408 accessConstrTags = accessConstrTags.prepend(ctag);
1409 return ctag;
1410 }
1411 }
1412
1413 /** Add all required access methods for a private symbol to enclosing class.
1414 * @param sym The symbol.
1415 */
1416 void makeAccessible(Symbol sym) {
1417 JCClassDecl cdef = classDef(sym.owner.enclClass());
1418 if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1419 if (sym.name == names.init) {
1420 cdef.defs = cdef.defs.prepend(
1421 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1422 } else {
1423 MethodSymbol[] accessors = accessSyms.get(sym);
1424 for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
1540
1541 /** A stack containing the this$n field of the currently translated
1542 * classes (if needed) in innermost first order.
1543 * Inside a constructor, proxies and any this$n symbol are duplicated
1544 * in an additional innermost scope, where they represent the constructor
1545 * parameters.
1546 */
1547 List<VarSymbol> outerThisStack;
1548
1549 /** The name of a free variable proxy.
1550 */
1551 Name proxyName(Name name, int index) {
1552 Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1553 if (index > 0) {
1554 proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1555 }
1556 return proxyName;
1557 }
1558
1559 /** Proxy definitions for all free variables in given list, in reverse order.
1560 * @param pos The source code position of the definition.
1561 * @param freevars The free variables.
1562 * @param owner The class in which the definitions go.
1563 * @param additionalFlags Any additional flags
1564 */
1565 List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1566 long additionalFlags) {
1567 long flags = FINAL | SYNTHETIC | additionalFlags;
1568 List<JCVariableDecl> defs = List.nil();
1569 Set<Name> proxyNames = new HashSet<>();
1570 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1571 VarSymbol v = l.head;
1572 int index = 0;
1573 Name proxyName;
1574 do {
1575 proxyName = proxyName(v.name, index++);
1576 } while (!proxyNames.add(proxyName));
1577 VarSymbol proxy = new VarSymbol(
1578 flags, proxyName, v.erasure(types), owner);
1579 proxies.put(v, proxy);
1580 JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1581 vd.vartype = access(vd.vartype);
1582 defs = defs.prepend(vd);
1583 }
1584 return defs;
1625 JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1626 ClassSymbol c = owner.enclClass();
1627 boolean isMandated =
1628 // Anonymous constructors
1629 (owner.isConstructor() && owner.isAnonymous()) ||
1630 // Constructors of non-private inner member classes
1631 (owner.isConstructor() && c.isInner() &&
1632 !c.isPrivate() && !c.isStatic());
1633 long flags =
1634 FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1635 VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1636 owner.extraParams = owner.extraParams.prepend(outerThis);
1637 return makeOuterThisVarDecl(pos, outerThis);
1638 }
1639
1640 /** Definition for this$n field.
1641 * @param pos The source code position of the definition.
1642 * @param owner The class in which the definition goes.
1643 */
1644 JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1645 VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | (allowValueClasses && owner.isValueClass() ? STRICT : 0));
1646 return makeOuterThisVarDecl(pos, outerThis);
1647 }
1648
1649 /** Return a list of trees that load the free variables in given list,
1650 * in reverse order.
1651 * @param pos The source code position to be used for the trees.
1652 * @param freevars The list of free variables.
1653 */
1654 List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1655 List<JCExpression> args = List.nil();
1656 for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1657 args = args.prepend(loadFreevar(pos, l.head));
1658 return args;
1659 }
1660 //where
1661 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1662 return access(v, make.at(pos).Ident(v), null, false);
1663 }
1664
1665 /** Construct a tree simulating the expression {@code C.this}.
1832 // create resource.close() method invocation
1833 JCExpression resourceClose = makeCall(resource,
1834 names.close,
1835 List.nil());
1836 return make.Exec(resourceClose);
1837 }
1838
1839 private JCExpression makeNonNullCheck(JCExpression expression) {
1840 return makeBinary(NE, expression, makeNull());
1841 }
1842
1843 /** Construct a tree that represents the outer instance
1844 * {@code C.this}. Never pick the current `this'.
1845 * @param pos The source code position to be used for the tree.
1846 * @param c The qualifier class.
1847 */
1848 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1849 List<VarSymbol> ots = outerThisStack;
1850 if (ots.isEmpty()) {
1851 log.error(pos, Errors.NoEnclInstanceOfTypeInScope(c));
1852 return makeNull();
1853 }
1854 VarSymbol ot = ots.head;
1855 JCExpression tree = access(make.at(pos).Ident(ot));
1856 ot.flags_field &= ~NOOUTERTHIS;
1857 TypeSymbol otc = ot.type.tsym;
1858 while (otc != c) {
1859 do {
1860 ots = ots.tail;
1861 if (ots.isEmpty()) {
1862 log.error(pos, Errors.NoEnclInstanceOfTypeInScope(c));
1863 Assert.error(); // should have been caught in Attr
1864 return tree;
1865 }
1866 ot = ots.head;
1867 } while (ot.owner != otc);
1868 if (otc.owner.kind != PCK && !otc.hasOuterInstance()) {
1869 log.error(pos, Errors.NoEnclInstanceOfTypeInScope(c));
1870 Assert.error(); // should have been caught in Attr
1871 return makeNull();
1957 }
1958
1959 /**************************************************************************
1960 * Code for .class
1961 *************************************************************************/
1962
1963 /** Return the symbol of a class to contain a cache of
1964 * compiler-generated statics such as class$ and the
1965 * $assertionsDisabled flag. We create an anonymous nested class
1966 * (unless one already exists) and return its symbol. However,
1967 * for backward compatibility in 1.4 and earlier we use the
1968 * top-level class itself.
1969 */
1970 private ClassSymbol outerCacheClass() {
1971 ClassSymbol clazz = outermostClassDef.sym;
1972 Scope s = clazz.members();
1973 for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1974 if (sym.kind == TYP &&
1975 sym.name == names.empty &&
1976 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1977 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1978 return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1979 }
1980
1981 /** Create an attributed tree of the form left.name(). */
1982 private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1983 Assert.checkNonNull(left.type);
1984 Symbol funcsym = lookupMethod(make_pos, name, left.type,
1985 TreeInfo.types(args));
1986 return make.App(make.Select(left, funcsym), args);
1987 }
1988
1989 /** The tree simulating a T.class expression.
1990 * @param clazz The tree identifying type T.
1991 */
1992 private JCExpression classOf(JCTree clazz) {
1993 return classOfType(clazz.type, clazz.pos());
1994 }
1995
1996 private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1997 switch (type.getTag()) {
1998 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2010 VarSymbol sym = new VarSymbol(
2011 STATIC | PUBLIC | FINAL, names._class,
2012 syms.classType, type.tsym);
2013 return make_at(pos).Select(make.Type(type), sym);
2014 default:
2015 throw new AssertionError();
2016 }
2017 }
2018
2019 /**************************************************************************
2020 * Code for enabling/disabling assertions.
2021 *************************************************************************/
2022
2023 private ClassSymbol assertionsDisabledClassCache;
2024
2025 /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
2026 */
2027 private ClassSymbol assertionsDisabledClass() {
2028 if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
2029
2030 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
2031 assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
2032
2033 return assertionsDisabledClassCache;
2034 }
2035
2036 // This code is not particularly robust if the user has
2037 // previously declared a member named '$assertionsDisabled'.
2038 // The same faulty idiom also appears in the translation of
2039 // class literals above. We should report an error if a
2040 // previous declaration is not synthetic.
2041
2042 private JCExpression assertFlagTest(DiagnosticPosition pos) {
2043 // Outermost class may be either true class or an interface.
2044 ClassSymbol outermostClass = outermostClassDef.sym;
2045
2046 //only classes can hold a non-public field, look for a usable one:
2047 ClassSymbol container = !currentClass.isInterface() ? currentClass :
2048 assertionsDisabledClass();
2049
2050 VarSymbol assertDisabledSym =
2051 (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
2299 proxies = new HashMap<>(proxies);
2300 List<VarSymbol> prevOuterThisStack = outerThisStack;
2301
2302 // If this is an enum definition
2303 if ((tree.mods.flags & ENUM) != 0 &&
2304 (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2305 visitEnumDef(tree);
2306
2307 if ((tree.mods.flags & RECORD) != 0) {
2308 visitRecordDef(tree);
2309 }
2310
2311 // If this is a nested class, define a this$n field for
2312 // it and add to proxies.
2313 JCVariableDecl otdef = null;
2314 if (currentClass.hasOuterInstance())
2315 otdef = outerThisDef(tree.pos, currentClass);
2316
2317 // If this is a local class, define proxies for all its free variables.
2318 List<JCVariableDecl> fvdefs = freevarDefs(
2319 tree.pos, freevars(currentClass), currentClass, allowValueClasses && currentClass.isValueClass() ? STRICT : 0);
2320
2321 // Recursively translate superclass, interfaces.
2322 tree.extending = translate(tree.extending);
2323 tree.implementing = translate(tree.implementing);
2324
2325 if (currentClass.isDirectlyOrIndirectlyLocal()) {
2326 ClassSymbol encl = currentClass.owner.enclClass();
2327 if (encl.trans_local == null) {
2328 encl.trans_local = List.nil();
2329 }
2330 encl.trans_local = encl.trans_local.prepend(currentClass);
2331 }
2332
2333 // Recursively translate members, taking into account that new members
2334 // might be created during the translation and prepended to the member
2335 // list `tree.defs'.
2336 List<JCTree> seen = List.nil();
2337 while (tree.defs != seen) {
2338 List<JCTree> unseen = tree.defs;
2339 for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2876 } else {
2877 Map<Symbol, Symbol> prevLambdaTranslationMap =
2878 lambdaTranslationMap;
2879 try {
2880 lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 &&
2881 tree.sym.name.startsWith(names.lambda) ?
2882 makeTranslationMap(tree) : null;
2883 super.visitMethodDef(tree);
2884 } finally {
2885 lambdaTranslationMap = prevLambdaTranslationMap;
2886 }
2887 }
2888 if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2889 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2890 // lets find out if there is any field waiting to be initialized
2891 ListBuffer<VarSymbol> fields = new ListBuffer<>();
2892 for (Symbol sym : currentClass.getEnclosedElements()) {
2893 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2894 fields.append((VarSymbol) sym);
2895 }
2896 ListBuffer<JCStatement> initializers = new ListBuffer<>();
2897 for (VarSymbol field: fields) {
2898 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2899 VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2900 make.at(tree.pos);
2901 initializers.add(make.Exec(
2902 make.Assign(
2903 make.Select(make.This(field.owner.erasure(types)), field),
2904 make.Ident(param)).setType(field.erasure(types))));
2905 field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2906 }
2907 }
2908 if (initializers.nonEmpty()) {
2909 if (tree.sym.owner.isValueClass()) {
2910 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2911 } else {
2912 tree.body.stats = tree.body.stats.appendList(initializers);
2913 }
2914 }
2915 }
2916 result = tree;
2917 }
2918 //where
2919 private Map<Symbol, Symbol> makeTranslationMap(JCMethodDecl tree) {
2920 Map<Symbol, Symbol> translationMap = new HashMap<>();
2921 for (JCVariableDecl vd : tree.params) {
2922 Symbol p = vd.sym;
2923 if (p != p.baseSymbol()) {
2924 translationMap.put(p.baseSymbol(), p);
2925 }
2926 }
2927 return translationMap;
2928 }
2929
2930 public void visitTypeCast(JCTypeCast tree) {
2931 tree.clazz = translate(tree.clazz);
2932 if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2933 tree.expr = translate(tree.expr, tree.type);
2934 else
3128 Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
3129 if (constructor != tree.constructor) {
3130 tree.args = tree.args.append(makeNull());
3131 tree.constructor = constructor;
3132 }
3133
3134 // If created class has an outer instance, and new is qualified, pass
3135 // qualifier as first argument. If new is not qualified, pass the
3136 // correct outer instance as first argument.
3137 if (c.hasOuterInstance()) {
3138 JCExpression thisArg;
3139 if (tree.encl != null) {
3140 thisArg = attr.makeNullCheck(translate(tree.encl));
3141 thisArg.type = tree.encl.type;
3142 } else if (c.isDirectlyOrIndirectlyLocal()) {
3143 // local class
3144 thisArg = makeThis(tree.pos(), c.type.getEnclosingType().tsym);
3145 } else {
3146 // nested class
3147 thisArg = makeOwnerThis(tree.pos(), c, false);
3148 if (currentMethodSym != null &&
3149 ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
3150 currentMethodSym.owner.isValueClass()) {
3151 // instance initializer in a value class
3152 Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
3153 if (outerThisSet == null) {
3154 outerThisSet = new HashSet<>();
3155 }
3156 outerThisSet.add(thisArg);
3157 initializerOuterThis.put(currentClass, outerThisSet);
3158 }
3159 }
3160 tree.args = tree.args.prepend(thisArg);
3161 }
3162 tree.encl = null;
3163
3164 // If we have an anonymous class, create its flat version, rather
3165 // than the class or interface following new.
3166 if (tree.def != null) {
3167 Map<Symbol, Symbol> prevLambdaTranslationMap = lambdaTranslationMap;
3168 try {
3169 lambdaTranslationMap = null;
3170 translate(tree.def);
3171 } finally {
3172 lambdaTranslationMap = prevLambdaTranslationMap;
3173 }
3174
3175 tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3176 tree.def = null;
3177 } else {
3178 tree.clazz = access(c, tree.clazz, enclOp, false);
|