< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page

  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);
< prev index next >