< prev index next >

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

Print this page

   1 /*
   2  * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any

  89     private final Symtab syms;
  90     private final Resolve rs;
  91     private final Operators operators;
  92     private final Check chk;
  93     private final Attr attr;
  94     private TreeMaker make;
  95     private DiagnosticPosition make_pos;
  96     private final ConstFold cfolder;
  97     private final Target target;
  98     private final TypeEnvs typeEnvs;
  99     private final Name dollarAssertionsDisabled;
 100     private final Types types;
 101     private final TransTypes transTypes;
 102     private final boolean debugLower;
 103     private final boolean disableProtectedAccessors; // experimental
 104     private final PkgInfo pkginfoOpt;
 105     private final boolean optimizeOuterThis;
 106     private final boolean nullCheckOuterThis;
 107     private final boolean useMatchException;
 108     private final HashMap<TypePairs, String> typePairToName;

 109     private int variableIndex = 0;
 110 
 111     @SuppressWarnings("this-escape")
 112     protected Lower(Context context) {
 113         context.put(lowerKey, this);
 114         names = Names.instance(context);
 115         log = Log.instance(context);
 116         syms = Symtab.instance(context);
 117         rs = Resolve.instance(context);
 118         operators = Operators.instance(context);
 119         chk = Check.instance(context);
 120         attr = Attr.instance(context);
 121         make = TreeMaker.instance(context);
 122         cfolder = ConstFold.instance(context);
 123         target = Target.instance(context);
 124         typeEnvs = TypeEnvs.instance(context);
 125         dollarAssertionsDisabled = names.
 126             fromString(target.syntheticNameChar() + "assertionsDisabled");
 127 
 128         types = Types.instance(context);
 129         transTypes = TransTypes.instance(context);
 130         Options options = Options.instance(context);
 131         debugLower = options.isSet("debuglower");
 132         pkginfoOpt = PkgInfo.get(options);
 133         optimizeOuterThis =
 134             target.optimizeOuterThis() ||
 135             options.getBoolean("optimizeOuterThis", false);
 136         nullCheckOuterThis = options.getBoolean("nullCheckOuterThis",
 137             target.nullCheckOuterThisByDefault());
 138         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 139         Source source = Source.instance(context);
 140         Preview preview = Preview.instance(context);
 141         useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
 142                             (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
 143         typePairToName = TypePairs.initialize(syms);


 144     }
 145 
 146     /** The currently enclosing class.
 147      */
 148     ClassSymbol currentClass;
 149 
 150     /** A queue of all translated classes.
 151      */
 152     ListBuffer<JCTree> translated;
 153 
 154     /** Environment for symbol lookup, set by translateTopLevelClass.
 155      */
 156     Env<AttrContext> attrEnv;
 157 
 158 /* ************************************************************************
 159  * Global mappings
 160  *************************************************************************/
 161 
 162     /** A hash table mapping local classes to their definitions.
 163      */

 176      * The current expected return type.
 177      */
 178     Type currentRestype;
 179 
 180     /** The current method definition.
 181      */
 182     JCMethodDecl currentMethodDef;
 183 
 184     /** The current method symbol.
 185      */
 186     MethodSymbol currentMethodSym;
 187 
 188     /** The currently enclosing outermost class definition.
 189      */
 190     JCClassDecl outermostClassDef;
 191 
 192     /** The currently enclosing outermost member definition.
 193      */
 194     JCTree outermostMemberDef;
 195 




 196     /** A navigator class for assembling a mapping from local class symbols
 197      *  to class definition trees.
 198      *  There is only one case; all other cases simply traverse down the tree.
 199      */
 200     class ClassMap extends TreeScanner {
 201 
 202         /** All encountered class defs are entered into classdefs table.
 203          */
 204         public void visitClassDef(JCClassDecl tree) {
 205             classdefs.put(tree.sym, tree);
 206             super.visitClassDef(tree);
 207         }
 208     }
 209     ClassMap classMap = new ClassMap();
 210 
 211     /** Map a class symbol to its definition.
 212      *  @param c    The class symbol of which we want to determine the definition.
 213      */
 214     JCClassDecl classDef(ClassSymbol c) {
 215         // First lookup the class in the classdefs table.

 754 
 755     /** Look up a method in a given scope.
 756      */
 757     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 758         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 759     }
 760 
 761     /** Anon inner classes are used as access constructor tags.
 762      * accessConstructorTag will use an existing anon class if one is available,
 763      * and synthesize a class (with makeEmptyClass) if one is not available.
 764      * However, there is a small possibility that an existing class will not
 765      * be generated as expected if it is inside a conditional with a constant
 766      * expression. If that is found to be the case, create an empty class tree here.
 767      */
 768     private void checkAccessConstructorTags() {
 769         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 770             ClassSymbol c = l.head;
 771             if (isTranslatedClassAvailable(c))
 772                 continue;
 773             // Create class definition tree.
 774             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,

 775                     c.outermostClass(), c.flatname, false);
 776             swapAccessConstructorTag(c, cdec.sym);
 777             translated.append(cdec);
 778         }
 779     }
 780     // where
 781     private boolean isTranslatedClassAvailable(ClassSymbol c) {
 782         for (JCTree tree: translated) {
 783             if (tree.hasTag(CLASSDEF)
 784                     && ((JCClassDecl) tree).sym == c) {
 785                 return true;
 786             }
 787         }
 788         return false;
 789     }
 790 
 791     void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
 792         for (MethodSymbol methodSymbol : accessConstrs.values()) {
 793             Assert.check(methodSymbol.type.hasTag(METHOD));
 794             MethodType oldMethodType =

1226                 accessConstrs.put(constr, aconstr);
1227                 accessed.append(constr);
1228             }
1229             return aconstr;
1230         } else {
1231             return constr;
1232         }
1233     }
1234 
1235     /** Return an anonymous class nested in this toplevel class.
1236      */
1237     ClassSymbol accessConstructorTag() {
1238         ClassSymbol topClass = currentClass.outermostClass();
1239         ModuleSymbol topModle = topClass.packge().modle;
1240         for (int i = 1; ; i++) {
1241             Name flatname = names.fromString("" + topClass.getQualifiedName() +
1242                                             target.syntheticNameChar() +
1243                                             i);
1244             ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1245             if (ctag == null)
1246                 ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;

1247             else if (!ctag.isAnonymous())
1248                 continue;
1249             // keep a record of all tags, to verify that all are generated as required
1250             accessConstrTags = accessConstrTags.prepend(ctag);
1251             return ctag;
1252         }
1253     }
1254 
1255     /** Add all required access methods for a private symbol to enclosing class.
1256      *  @param sym       The symbol.
1257      */
1258     void makeAccessible(Symbol sym) {
1259         JCClassDecl cdef = classDef(sym.owner.enclClass());
1260         if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1261         if (sym.name == names.init) {
1262             cdef.defs = cdef.defs.prepend(
1263                 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1264         } else {
1265             MethodSymbol[] accessors = accessSyms.get(sym);
1266             for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {

1382 
1383     /** A stack containing the this$n field of the currently translated
1384      *  classes (if needed) in innermost first order.
1385      *  Inside a constructor, proxies and any this$n symbol are duplicated
1386      *  in an additional innermost scope, where they represent the constructor
1387      *  parameters.
1388      */
1389     List<VarSymbol> outerThisStack;
1390 
1391     /** The name of a free variable proxy.
1392      */
1393     Name proxyName(Name name, int index) {
1394         Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1395         if (index > 0) {
1396             proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1397         }
1398         return proxyName;
1399     }
1400 
1401     /** Proxy definitions for all free variables in given list, in reverse order.
1402      *  @param pos        The source code position of the definition.
1403      *  @param freevars   The free variables.
1404      *  @param owner      The class in which the definitions go.

1405      */
1406     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1407         return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1408     }
1409 
1410     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1411             long additionalFlags) {
1412         long flags = FINAL | SYNTHETIC | additionalFlags;
1413         List<JCVariableDecl> defs = List.nil();
1414         Set<Name> proxyNames = new HashSet<>();
1415         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1416             VarSymbol v = l.head;
1417             int index = 0;
1418             Name proxyName;
1419             do {
1420                 proxyName = proxyName(v.name, index++);
1421             } while (!proxyNames.add(proxyName));
1422             VarSymbol proxy = new VarSymbol(
1423                 flags, proxyName, v.erasure(types), owner) {
1424                 @Override

1475     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1476         ClassSymbol c = owner.enclClass();
1477         boolean isMandated =
1478             // Anonymous constructors
1479             (owner.isConstructor() && owner.isAnonymous()) ||
1480             // Constructors of non-private inner member classes
1481             (owner.isConstructor() && c.isInner() &&
1482              !c.isPrivate() && !c.isStatic());
1483         long flags =
1484             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1485         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1486         owner.extraParams = owner.extraParams.prepend(outerThis);
1487         return makeOuterThisVarDecl(pos, outerThis);
1488     }
1489 
1490     /** Definition for this$n field.
1491      *  @param pos        The source code position of the definition.
1492      *  @param owner      The class in which the definition goes.
1493      */
1494     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1495         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
1496         return makeOuterThisVarDecl(pos, outerThis);
1497     }
1498 
1499     /** Return a list of trees that load the free variables in given list,
1500      *  in reverse order.
1501      *  @param pos          The source code position to be used for the trees.
1502      *  @param freevars     The list of free variables.
1503      */
1504     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1505         List<JCExpression> args = List.nil();
1506         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1507             args = args.prepend(loadFreevar(pos, l.head));
1508         return args;
1509     }
1510 //where
1511         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1512             return access(v, make.at(pos).Ident(v), null, false);
1513         }
1514 
1515     /** Construct a tree simulating the expression {@code C.this}.

1815     }
1816 
1817 /* ************************************************************************
1818  * Code for .class
1819  *************************************************************************/
1820 
1821     /** Return the symbol of a class to contain a cache of
1822      *  compiler-generated statics such as class$ and the
1823      *  $assertionsDisabled flag.  We create an anonymous nested class
1824      *  (unless one already exists) and return its symbol.  However,
1825      *  for backward compatibility in 1.4 and earlier we use the
1826      *  top-level class itself.
1827      */
1828     private ClassSymbol outerCacheClass() {
1829         ClassSymbol clazz = outermostClassDef.sym;
1830         Scope s = clazz.members();
1831         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1832             if (sym.kind == TYP &&
1833                 sym.name == names.empty &&
1834                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1835         return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;

1836     }
1837 
1838     /** Create an attributed tree of the form left.name(). */
1839     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1840         Assert.checkNonNull(left.type);
1841         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1842                                       TreeInfo.types(args));
1843         return make.App(make.Select(left, funcsym), args);
1844     }
1845 
1846     /** The tree simulating a T.class expression.
1847      *  @param clazz      The tree identifying type T.
1848      */
1849     private JCExpression classOf(JCTree clazz) {
1850         return classOfType(clazz.type, clazz.pos());
1851     }
1852 
1853     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1854         switch (type.getTag()) {
1855         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1867                 VarSymbol sym = new VarSymbol(
1868                         STATIC | PUBLIC | FINAL, names._class,
1869                         syms.classType, type.tsym);
1870                 return make_at(pos).Select(make.Type(type), sym);
1871         default:
1872             throw new AssertionError();
1873         }
1874     }
1875 
1876 /* ************************************************************************
1877  * Code for enabling/disabling assertions.
1878  *************************************************************************/
1879 
1880     private ClassSymbol assertionsDisabledClassCache;
1881 
1882     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1883      */
1884     private ClassSymbol assertionsDisabledClass() {
1885         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1886 
1887         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;

1888 
1889         return assertionsDisabledClassCache;
1890     }
1891 
1892     // This code is not particularly robust if the user has
1893     // previously declared a member named '$assertionsDisabled'.
1894     // The same faulty idiom also appears in the translation of
1895     // class literals above.  We should report an error if a
1896     // previous declaration is not synthetic.
1897 
1898     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1899         // Outermost class may be either true class or an interface.
1900         ClassSymbol outermostClass = outermostClassDef.sym;
1901 
1902         //only classes can hold a non-public field, look for a usable one:
1903         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1904                 assertionsDisabledClass();
1905 
1906         VarSymbol assertDisabledSym =
1907             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

2155         proxies = new HashMap<>(proxies);
2156         List<VarSymbol> prevOuterThisStack = outerThisStack;
2157 
2158         // If this is an enum definition
2159         if ((tree.mods.flags & ENUM) != 0 &&
2160             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2161             visitEnumDef(tree);
2162 
2163         if ((tree.mods.flags & RECORD) != 0) {
2164             visitRecordDef(tree);
2165         }
2166 
2167         // If this is a nested class, define a this$n field for
2168         // it and add to proxies.
2169         JCVariableDecl otdef = null;
2170         if (currentClass.hasOuterInstance())
2171             otdef = outerThisDef(tree.pos, currentClass);
2172 
2173         // If this is a local class, define proxies for all its free variables.
2174         List<JCVariableDecl> fvdefs = freevarDefs(
2175             tree.pos, freevars(currentClass), currentClass);
2176 
2177         // Recursively translate superclass, interfaces.
2178         tree.extending = translate(tree.extending);
2179         tree.implementing = translate(tree.implementing);
2180 
2181         if (currentClass.isDirectlyOrIndirectlyLocal()) {
2182             ClassSymbol encl = currentClass.owner.enclClass();
2183             if (encl.trans_local == null) {
2184                 encl.trans_local = List.nil();
2185             }
2186             encl.trans_local = encl.trans_local.prepend(currentClass);
2187         }
2188 
2189         // Recursively translate members, taking into account that new members
2190         // might be created during the translation and prepended to the member
2191         // list `tree.defs'.
2192         List<JCTree> seen = List.nil();
2193         while (tree.defs != seen) {
2194             List<JCTree> unseen = tree.defs;
2195             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {

2736             if (added.nonEmpty()) {
2737                 List<JCStatement> initializers = added.toList();
2738                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2739             }
2740 
2741             // pop local variables from proxy stack
2742             proxies = prevProxies;
2743 
2744             outerThisStack = prevOuterThisStack;
2745         } else {
2746             super.visitMethodDef(tree);
2747         }
2748         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2749                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2750             // lets find out if there is any field waiting to be initialized
2751             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2752             for (Symbol sym : currentClass.getEnclosedElements()) {
2753                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2754                     fields.append((VarSymbol) sym);
2755             }

2756             for (VarSymbol field: fields) {
2757                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2758                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2759                     make.at(tree.pos);
2760                     tree.body.stats = tree.body.stats.append(
2761                             make.Exec(
2762                                     make.Assign(
2763                                             make.Select(make.This(field.owner.erasure(types)), field),
2764                                             make.Ident(param)).setType(field.erasure(types))));
2765                     // we don't need the flag at the field anymore
2766                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2767                 }
2768             }







2769         }
2770         result = tree;
2771     }
2772 
2773     public void visitTypeCast(JCTypeCast tree) {
2774         tree.clazz = translate(tree.clazz);
2775         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2776             tree.expr = translate(tree.expr, tree.type);
2777         else
2778             tree.expr = translate(tree.expr);
2779         result = tree;
2780     }
2781 
2782     /**
2783      * All the exactness checks between primitive types that require a run-time
2784      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2785      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2786      * {@code S} and {@code T} are primitive types and correspond to the runtime
2787      * action that will be executed to check whether a certain value (that is passed
2788      * as a parameter) can be converted to {@code T} without loss of information.

2972         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2973         if (constructor != tree.constructor) {
2974             tree.args = tree.args.append(makeNull());
2975             tree.constructor = constructor;
2976         }
2977 
2978         // If created class has an outer instance, and new is qualified, pass
2979         // qualifier as first argument. If new is not qualified, pass the
2980         // correct outer instance as first argument.
2981         if (c.hasOuterInstance()) {
2982             JCExpression thisArg;
2983             if (tree.encl != null) {
2984                 thisArg = attr.makeNullCheck(translate(tree.encl));
2985                 thisArg.type = tree.encl.type;
2986             } else if (c.isDirectlyOrIndirectlyLocal()) {
2987                 // local class
2988                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
2989             } else {
2990                 // nested class
2991                 thisArg = makeOwnerThis(tree.pos(), c, false);











2992             }
2993             tree.args = tree.args.prepend(thisArg);
2994         }
2995         tree.encl = null;
2996 
2997         // If we have an anonymous class, create its flat version, rather
2998         // than the class or interface following new.
2999         if (tree.def != null) {
3000             translate(tree.def);
3001 
3002             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3003             tree.def = null;
3004         } else {
3005             tree.clazz = access(c, tree.clazz, enclOp, false);
3006         }
3007         result = tree;
3008     }
3009 
3010     // Simplify conditionals with known constant controlling expressions.
3011     // This allows us to avoid generating supporting declarations for

   1 /*
   2  * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any

  89     private final Symtab syms;
  90     private final Resolve rs;
  91     private final Operators operators;
  92     private final Check chk;
  93     private final Attr attr;
  94     private TreeMaker make;
  95     private DiagnosticPosition make_pos;
  96     private final ConstFold cfolder;
  97     private final Target target;
  98     private final TypeEnvs typeEnvs;
  99     private final Name dollarAssertionsDisabled;
 100     private final Types types;
 101     private final TransTypes transTypes;
 102     private final boolean debugLower;
 103     private final boolean disableProtectedAccessors; // experimental
 104     private final PkgInfo pkginfoOpt;
 105     private final boolean optimizeOuterThis;
 106     private final boolean nullCheckOuterThis;
 107     private final boolean useMatchException;
 108     private final HashMap<TypePairs, String> typePairToName;
 109     private final boolean allowValueClasses;
 110     private int variableIndex = 0;
 111 
 112     @SuppressWarnings("this-escape")
 113     protected Lower(Context context) {
 114         context.put(lowerKey, this);
 115         names = Names.instance(context);
 116         log = Log.instance(context);
 117         syms = Symtab.instance(context);
 118         rs = Resolve.instance(context);
 119         operators = Operators.instance(context);
 120         chk = Check.instance(context);
 121         attr = Attr.instance(context);
 122         make = TreeMaker.instance(context);
 123         cfolder = ConstFold.instance(context);
 124         target = Target.instance(context);
 125         typeEnvs = TypeEnvs.instance(context);
 126         dollarAssertionsDisabled = names.
 127             fromString(target.syntheticNameChar() + "assertionsDisabled");
 128 
 129         types = Types.instance(context);
 130         transTypes = TransTypes.instance(context);
 131         Options options = Options.instance(context);
 132         debugLower = options.isSet("debuglower");
 133         pkginfoOpt = PkgInfo.get(options);
 134         optimizeOuterThis =
 135             target.optimizeOuterThis() ||
 136             options.getBoolean("optimizeOuterThis", false);
 137         nullCheckOuterThis = options.getBoolean("nullCheckOuterThis",
 138             target.nullCheckOuterThisByDefault());
 139         disableProtectedAccessors = options.isSet("disableProtectedAccessors");
 140         Source source = Source.instance(context);
 141         Preview preview = Preview.instance(context);
 142         useMatchException = Feature.PATTERN_SWITCH.allowedInSource(source) &&
 143                             (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH));
 144         typePairToName = TypePairs.initialize(syms);
 145         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 146                 Feature.VALUE_CLASSES.allowedInSource(source);
 147     }
 148 
 149     /** The currently enclosing class.
 150      */
 151     ClassSymbol currentClass;
 152 
 153     /** A queue of all translated classes.
 154      */
 155     ListBuffer<JCTree> translated;
 156 
 157     /** Environment for symbol lookup, set by translateTopLevelClass.
 158      */
 159     Env<AttrContext> attrEnv;
 160 
 161 /* ************************************************************************
 162  * Global mappings
 163  *************************************************************************/
 164 
 165     /** A hash table mapping local classes to their definitions.
 166      */

 179      * The current expected return type.
 180      */
 181     Type currentRestype;
 182 
 183     /** The current method definition.
 184      */
 185     JCMethodDecl currentMethodDef;
 186 
 187     /** The current method symbol.
 188      */
 189     MethodSymbol currentMethodSym;
 190 
 191     /** The currently enclosing outermost class definition.
 192      */
 193     JCClassDecl outermostClassDef;
 194 
 195     /** The currently enclosing outermost member definition.
 196      */
 197     JCTree outermostMemberDef;
 198 
 199     /** A hash table mapping local classes to a set of outer this fields
 200      */
 201     public Map<ClassSymbol, Set<JCExpression>> initializerOuterThis = new WeakHashMap<>();
 202 
 203     /** A navigator class for assembling a mapping from local class symbols
 204      *  to class definition trees.
 205      *  There is only one case; all other cases simply traverse down the tree.
 206      */
 207     class ClassMap extends TreeScanner {
 208 
 209         /** All encountered class defs are entered into classdefs table.
 210          */
 211         public void visitClassDef(JCClassDecl tree) {
 212             classdefs.put(tree.sym, tree);
 213             super.visitClassDef(tree);
 214         }
 215     }
 216     ClassMap classMap = new ClassMap();
 217 
 218     /** Map a class symbol to its definition.
 219      *  @param c    The class symbol of which we want to determine the definition.
 220      */
 221     JCClassDecl classDef(ClassSymbol c) {
 222         // First lookup the class in the classdefs table.

 761 
 762     /** Look up a method in a given scope.
 763      */
 764     private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
 765         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
 766     }
 767 
 768     /** Anon inner classes are used as access constructor tags.
 769      * accessConstructorTag will use an existing anon class if one is available,
 770      * and synthesize a class (with makeEmptyClass) if one is not available.
 771      * However, there is a small possibility that an existing class will not
 772      * be generated as expected if it is inside a conditional with a constant
 773      * expression. If that is found to be the case, create an empty class tree here.
 774      */
 775     private void checkAccessConstructorTags() {
 776         for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
 777             ClassSymbol c = l.head;
 778             if (isTranslatedClassAvailable(c))
 779                 continue;
 780             // Create class definition tree.
 781             // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
 782             JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
 783                     c.outermostClass(), c.flatname, false);
 784             swapAccessConstructorTag(c, cdec.sym);
 785             translated.append(cdec);
 786         }
 787     }
 788     // where
 789     private boolean isTranslatedClassAvailable(ClassSymbol c) {
 790         for (JCTree tree: translated) {
 791             if (tree.hasTag(CLASSDEF)
 792                     && ((JCClassDecl) tree).sym == c) {
 793                 return true;
 794             }
 795         }
 796         return false;
 797     }
 798 
 799     void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) {
 800         for (MethodSymbol methodSymbol : accessConstrs.values()) {
 801             Assert.check(methodSymbol.type.hasTag(METHOD));
 802             MethodType oldMethodType =

1234                 accessConstrs.put(constr, aconstr);
1235                 accessed.append(constr);
1236             }
1237             return aconstr;
1238         } else {
1239             return constr;
1240         }
1241     }
1242 
1243     /** Return an anonymous class nested in this toplevel class.
1244      */
1245     ClassSymbol accessConstructorTag() {
1246         ClassSymbol topClass = currentClass.outermostClass();
1247         ModuleSymbol topModle = topClass.packge().modle;
1248         for (int i = 1; ; i++) {
1249             Name flatname = names.fromString("" + topClass.getQualifiedName() +
1250                                             target.syntheticNameChar() +
1251                                             i);
1252             ClassSymbol ctag = chk.getCompiled(topModle, flatname);
1253             if (ctag == null)
1254                 // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1255                 ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
1256             else if (!ctag.isAnonymous())
1257                 continue;
1258             // keep a record of all tags, to verify that all are generated as required
1259             accessConstrTags = accessConstrTags.prepend(ctag);
1260             return ctag;
1261         }
1262     }
1263 
1264     /** Add all required access methods for a private symbol to enclosing class.
1265      *  @param sym       The symbol.
1266      */
1267     void makeAccessible(Symbol sym) {
1268         JCClassDecl cdef = classDef(sym.owner.enclClass());
1269         if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
1270         if (sym.name == names.init) {
1271             cdef.defs = cdef.defs.prepend(
1272                 accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
1273         } else {
1274             MethodSymbol[] accessors = accessSyms.get(sym);
1275             for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {

1391 
1392     /** A stack containing the this$n field of the currently translated
1393      *  classes (if needed) in innermost first order.
1394      *  Inside a constructor, proxies and any this$n symbol are duplicated
1395      *  in an additional innermost scope, where they represent the constructor
1396      *  parameters.
1397      */
1398     List<VarSymbol> outerThisStack;
1399 
1400     /** The name of a free variable proxy.
1401      */
1402     Name proxyName(Name name, int index) {
1403         Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
1404         if (index > 0) {
1405             proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
1406         }
1407         return proxyName;
1408     }
1409 
1410     /** Proxy definitions for all free variables in given list, in reverse order.
1411      *  @param pos               The source code position of the definition.
1412      *  @param freevars          The free variables.
1413      *  @param owner             The class in which the definitions go.
1414      *  @param additionalFlags   Any additional flags
1415      */
1416     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
1417         return freevarDefs(pos, freevars, owner, LOCAL_CAPTURE_FIELD);
1418     }
1419 
1420     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
1421             long additionalFlags) {
1422         long flags = FINAL | SYNTHETIC | additionalFlags;
1423         List<JCVariableDecl> defs = List.nil();
1424         Set<Name> proxyNames = new HashSet<>();
1425         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1426             VarSymbol v = l.head;
1427             int index = 0;
1428             Name proxyName;
1429             do {
1430                 proxyName = proxyName(v.name, index++);
1431             } while (!proxyNames.add(proxyName));
1432             VarSymbol proxy = new VarSymbol(
1433                 flags, proxyName, v.erasure(types), owner) {
1434                 @Override

1485     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1486         ClassSymbol c = owner.enclClass();
1487         boolean isMandated =
1488             // Anonymous constructors
1489             (owner.isConstructor() && owner.isAnonymous()) ||
1490             // Constructors of non-private inner member classes
1491             (owner.isConstructor() && c.isInner() &&
1492              !c.isPrivate() && !c.isStatic());
1493         long flags =
1494             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1495         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1496         owner.extraParams = owner.extraParams.prepend(outerThis);
1497         return makeOuterThisVarDecl(pos, outerThis);
1498     }
1499 
1500     /** Definition for this$n field.
1501      *  @param pos        The source code position of the definition.
1502      *  @param owner      The class in which the definition goes.
1503      */
1504     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1505         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | (allowValueClasses && owner.isValueClass() ? STRICT : 0));
1506         return makeOuterThisVarDecl(pos, outerThis);
1507     }
1508 
1509     /** Return a list of trees that load the free variables in given list,
1510      *  in reverse order.
1511      *  @param pos          The source code position to be used for the trees.
1512      *  @param freevars     The list of free variables.
1513      */
1514     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1515         List<JCExpression> args = List.nil();
1516         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1517             args = args.prepend(loadFreevar(pos, l.head));
1518         return args;
1519     }
1520 //where
1521         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1522             return access(v, make.at(pos).Ident(v), null, false);
1523         }
1524 
1525     /** Construct a tree simulating the expression {@code C.this}.

1825     }
1826 
1827 /* ************************************************************************
1828  * Code for .class
1829  *************************************************************************/
1830 
1831     /** Return the symbol of a class to contain a cache of
1832      *  compiler-generated statics such as class$ and the
1833      *  $assertionsDisabled flag.  We create an anonymous nested class
1834      *  (unless one already exists) and return its symbol.  However,
1835      *  for backward compatibility in 1.4 and earlier we use the
1836      *  top-level class itself.
1837      */
1838     private ClassSymbol outerCacheClass() {
1839         ClassSymbol clazz = outermostClassDef.sym;
1840         Scope s = clazz.members();
1841         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1842             if (sym.kind == TYP &&
1843                 sym.name == names.empty &&
1844                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1845         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1846         return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1847     }
1848 
1849     /** Create an attributed tree of the form left.name(). */
1850     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1851         Assert.checkNonNull(left.type);
1852         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1853                                       TreeInfo.types(args));
1854         return make.App(make.Select(left, funcsym), args);
1855     }
1856 
1857     /** The tree simulating a T.class expression.
1858      *  @param clazz      The tree identifying type T.
1859      */
1860     private JCExpression classOf(JCTree clazz) {
1861         return classOfType(clazz.type, clazz.pos());
1862     }
1863 
1864     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1865         switch (type.getTag()) {
1866         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:

1878                 VarSymbol sym = new VarSymbol(
1879                         STATIC | PUBLIC | FINAL, names._class,
1880                         syms.classType, type.tsym);
1881                 return make_at(pos).Select(make.Type(type), sym);
1882         default:
1883             throw new AssertionError();
1884         }
1885     }
1886 
1887 /* ************************************************************************
1888  * Code for enabling/disabling assertions.
1889  *************************************************************************/
1890 
1891     private ClassSymbol assertionsDisabledClassCache;
1892 
1893     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1894      */
1895     private ClassSymbol assertionsDisabledClass() {
1896         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1897 
1898         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1899         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1900 
1901         return assertionsDisabledClassCache;
1902     }
1903 
1904     // This code is not particularly robust if the user has
1905     // previously declared a member named '$assertionsDisabled'.
1906     // The same faulty idiom also appears in the translation of
1907     // class literals above.  We should report an error if a
1908     // previous declaration is not synthetic.
1909 
1910     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1911         // Outermost class may be either true class or an interface.
1912         ClassSymbol outermostClass = outermostClassDef.sym;
1913 
1914         //only classes can hold a non-public field, look for a usable one:
1915         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1916                 assertionsDisabledClass();
1917 
1918         VarSymbol assertDisabledSym =
1919             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

2167         proxies = new HashMap<>(proxies);
2168         List<VarSymbol> prevOuterThisStack = outerThisStack;
2169 
2170         // If this is an enum definition
2171         if ((tree.mods.flags & ENUM) != 0 &&
2172             (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
2173             visitEnumDef(tree);
2174 
2175         if ((tree.mods.flags & RECORD) != 0) {
2176             visitRecordDef(tree);
2177         }
2178 
2179         // If this is a nested class, define a this$n field for
2180         // it and add to proxies.
2181         JCVariableDecl otdef = null;
2182         if (currentClass.hasOuterInstance())
2183             otdef = outerThisDef(tree.pos, currentClass);
2184 
2185         // If this is a local class, define proxies for all its free variables.
2186         List<JCVariableDecl> fvdefs = freevarDefs(
2187             tree.pos, freevars(currentClass), currentClass, allowValueClasses && currentClass.isValueClass() ? STRICT : LOCAL_CAPTURE_FIELD);
2188 
2189         // Recursively translate superclass, interfaces.
2190         tree.extending = translate(tree.extending);
2191         tree.implementing = translate(tree.implementing);
2192 
2193         if (currentClass.isDirectlyOrIndirectlyLocal()) {
2194             ClassSymbol encl = currentClass.owner.enclClass();
2195             if (encl.trans_local == null) {
2196                 encl.trans_local = List.nil();
2197             }
2198             encl.trans_local = encl.trans_local.prepend(currentClass);
2199         }
2200 
2201         // Recursively translate members, taking into account that new members
2202         // might be created during the translation and prepended to the member
2203         // list `tree.defs'.
2204         List<JCTree> seen = List.nil();
2205         while (tree.defs != seen) {
2206             List<JCTree> unseen = tree.defs;
2207             for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {

2748             if (added.nonEmpty()) {
2749                 List<JCStatement> initializers = added.toList();
2750                 TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.append(supercall)));
2751             }
2752 
2753             // pop local variables from proxy stack
2754             proxies = prevProxies;
2755 
2756             outerThisStack = prevOuterThisStack;
2757         } else {
2758             super.visitMethodDef(tree);
2759         }
2760         if (tree.name == names.init && ((tree.sym.flags_field & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
2761                 (tree.sym.flags_field & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD))) {
2762             // lets find out if there is any field waiting to be initialized
2763             ListBuffer<VarSymbol> fields = new ListBuffer<>();
2764             for (Symbol sym : currentClass.getEnclosedElements()) {
2765                 if (sym.kind == Kinds.Kind.VAR && ((sym.flags() & RECORD) != 0))
2766                     fields.append((VarSymbol) sym);
2767             }
2768             ListBuffer<JCStatement> initializers = new ListBuffer<>();
2769             for (VarSymbol field: fields) {
2770                 if ((field.flags_field & Flags.UNINITIALIZED_FIELD) != 0) {
2771                     VarSymbol param = tree.params.stream().filter(p -> p.name == field.name).findFirst().get().sym;
2772                     make.at(tree.pos);
2773                     initializers.add(make.Exec(
2774                             make.Assign(
2775                                     make.Select(make.This(field.owner.erasure(types)), field),
2776                                     make.Ident(param)).setType(field.erasure(types))));


2777                     field.flags_field &= ~Flags.UNINITIALIZED_FIELD;
2778                 }
2779             }
2780             if (initializers.nonEmpty()) {
2781                 if (allowValueClasses && (tree.sym.owner.isValueClass() || ((ClassSymbol)tree.sym.owner).isRecord())) {
2782                     TreeInfo.mapSuperCalls(tree.body, supercall -> make.Block(0, initializers.toList().append(supercall)));
2783                 } else {
2784                     tree.body.stats = tree.body.stats.appendList(initializers);
2785                 }
2786             }
2787         }
2788         result = tree;
2789     }
2790 
2791     public void visitTypeCast(JCTypeCast tree) {
2792         tree.clazz = translate(tree.clazz);
2793         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2794             tree.expr = translate(tree.expr, tree.type);
2795         else
2796             tree.expr = translate(tree.expr);
2797         result = tree;
2798     }
2799 
2800     /**
2801      * All the exactness checks between primitive types that require a run-time
2802      * check are in {@code java.lang.runtime.ExactConversionsSupport}. Those methods
2803      * are in the form {@code ExactConversionsSupport.is<S>To<T>Exact} where both
2804      * {@code S} and {@code T} are primitive types and correspond to the runtime
2805      * action that will be executed to check whether a certain value (that is passed
2806      * as a parameter) can be converted to {@code T} without loss of information.

2990         Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
2991         if (constructor != tree.constructor) {
2992             tree.args = tree.args.append(makeNull());
2993             tree.constructor = constructor;
2994         }
2995 
2996         // If created class has an outer instance, and new is qualified, pass
2997         // qualifier as first argument. If new is not qualified, pass the
2998         // correct outer instance as first argument.
2999         if (c.hasOuterInstance()) {
3000             JCExpression thisArg;
3001             if (tree.encl != null) {
3002                 thisArg = attr.makeNullCheck(translate(tree.encl));
3003                 thisArg.type = tree.encl.type;
3004             } else if (c.isDirectlyOrIndirectlyLocal()) {
3005                 // local class
3006                 thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingClass());
3007             } else {
3008                 // nested class
3009                 thisArg = makeOwnerThis(tree.pos(), c, false);
3010                 if (currentMethodSym != null &&
3011                         ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) &&
3012                         currentMethodSym.owner.isValueClass()) {
3013                     // instance initializer in a value class
3014                     Set<JCExpression> outerThisSet = initializerOuterThis.get(currentClass);
3015                     if (outerThisSet == null) {
3016                         outerThisSet = new HashSet<>();
3017                     }
3018                     outerThisSet.add(thisArg);
3019                     initializerOuterThis.put(currentClass, outerThisSet);
3020                 }
3021             }
3022             tree.args = tree.args.prepend(thisArg);
3023         }
3024         tree.encl = null;
3025 
3026         // If we have an anonymous class, create its flat version, rather
3027         // than the class or interface following new.
3028         if (tree.def != null) {
3029             translate(tree.def);
3030 
3031             tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
3032             tree.def = null;
3033         } else {
3034             tree.clazz = access(c, tree.clazz, enclOp, false);
3035         }
3036         result = tree;
3037     }
3038 
3039     // Simplify conditionals with known constant controlling expressions.
3040     // This allows us to avoid generating supporting declarations for
< prev index next >