< 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      */

 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
1425                 public Symbol baseSymbol() {
1426                     return v;
1427                 }

1435     }
1436 
1437     /** The name of a this$n field
1438      *  @param type   The class referenced by the this$n field
1439      */
1440     Name outerThisName(Type type, Symbol owner) {
1441         Type t = type.getEnclosingType();
1442         int nestingLevel = 0;
1443         while (t.hasTag(CLASS)) {
1444             t = t.getEnclosingType();
1445             nestingLevel++;
1446         }
1447         Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
1448         while (owner.kind == TYP && ((ClassSymbol)owner).members().findFirst(result) != null)
1449             result = names.fromString(result.toString() + target.syntheticNameChar());
1450         return result;
1451     }
1452 
1453     private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
1454         Type target = owner.innermostAccessibleEnclosingClass().erasure(types);
1455         // Set NOOUTERTHIS for all synthetic outer instance variables, and unset
1456         // it when the variable is accessed. If the variable is never accessed,
1457         // we skip creating an outer instance field and saving the constructor
1458         // parameter to it.
1459         VarSymbol outerThis =
1460             new VarSymbol(flags | NOOUTERTHIS, outerThisName(target, owner), target, owner);


1461         outerThisStack = outerThisStack.prepend(outerThis);
1462         return outerThis;
1463     }
1464 
1465     private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1466         JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1467         vd.vartype = access(vd.vartype);
1468         return vd;
1469     }
1470 
1471     /** Definition for this$n field.
1472      *  @param pos        The source code position of the definition.
1473      *  @param owner      The method in which the definition goes.
1474      */
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:
1856         case DOUBLE: case BOOLEAN: case VOID:
1857             // replace with <BoxedClass>.TYPE
1858             ClassSymbol c = types.boxedClass(type);
1859             Symbol typeSym =
1860                 rs.accessBase(
1861                     rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR),
1862                     pos, c.type, names.TYPE, true);
1863             if (typeSym.kind == VAR)
1864                 ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
1865             return make.QualIdent(typeSym);
1866         case CLASS: case ARRAY:
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,

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.

   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.isEnabled() && Feature.VALUE_CLASSES.allowedInSource(source);
 146     }
 147 
 148     /** The currently enclosing class.
 149      */
 150     ClassSymbol currentClass;
 151 
 152     /** A queue of all translated classes.
 153      */
 154     ListBuffer<JCTree> translated;
 155 
 156     /** Environment for symbol lookup, set by translateTopLevelClass.
 157      */
 158     Env<AttrContext> attrEnv;
 159 
 160 /* ************************************************************************
 161  * Global mappings
 162  *************************************************************************/
 163 
 164     /** A hash table mapping local classes to their definitions.
 165      */

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

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

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

1440     }
1441 
1442     /** The name of a this$n field
1443      *  @param type   The class referenced by the this$n field
1444      */
1445     Name outerThisName(Type type, Symbol owner) {
1446         Type t = type.getEnclosingType();
1447         int nestingLevel = 0;
1448         while (t.hasTag(CLASS)) {
1449             t = t.getEnclosingType();
1450             nestingLevel++;
1451         }
1452         Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
1453         while (owner.kind == TYP && ((ClassSymbol)owner).members().findFirst(result) != null)
1454             result = names.fromString(result.toString() + target.syntheticNameChar());
1455         return result;
1456     }
1457 
1458     private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
1459         Type target = owner.innermostAccessibleEnclosingClass().erasure(types);
1460         if (owner.kind == TYP) {
1461             // Set NOOUTERTHIS for all synthetic outer instance variables, and unset
1462             // it when the variable is accessed. If the variable is never accessed,
1463             // we skip creating an outer instance field and saving the constructor
1464             // parameter to it.
1465             flags = flags | NOOUTERTHIS | OUTER_THIS_FIELD;
1466         }
1467         VarSymbol outerThis = new VarSymbol(flags, outerThisName(target, owner), target, owner);
1468         outerThisStack = outerThisStack.prepend(outerThis);
1469         return outerThis;
1470     }
1471 
1472     private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
1473         JCVariableDecl vd = make.at(pos).VarDef(sym, null);
1474         vd.vartype = access(vd.vartype);
1475         return vd;
1476     }
1477 
1478     /** Definition for this$n field.
1479      *  @param pos        The source code position of the definition.
1480      *  @param owner      The method in which the definition goes.
1481      */
1482     JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
1483         ClassSymbol c = owner.enclClass();
1484         boolean isMandated =
1485             // Anonymous constructors
1486             (owner.isConstructor() && owner.isAnonymous()) ||
1487             // Constructors of non-private inner member classes
1488             (owner.isConstructor() && c.isInner() &&
1489              !c.isPrivate() && !c.isStatic());
1490         long flags =
1491             FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
1492         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
1493         owner.extraParams = owner.extraParams.prepend(outerThis);
1494         return makeOuterThisVarDecl(pos, outerThis);
1495     }
1496 
1497     /** Definition for this$n field.
1498      *  @param pos        The source code position of the definition.
1499      *  @param owner      The class in which the definition goes.
1500      */
1501     JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
1502         long strict = (allowValueClasses && owner.isValueClass()) ? STRICT : 0;
1503         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC | strict);
1504         return makeOuterThisVarDecl(pos, outerThis);
1505     }
1506 
1507     /** Return a list of trees that load the free variables in given list,
1508      *  in reverse order.
1509      *  @param pos          The source code position to be used for the trees.
1510      *  @param freevars     The list of free variables.
1511      */
1512     List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
1513         List<JCExpression> args = List.nil();
1514         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1515             args = args.prepend(loadFreevar(pos, l.head));
1516         return args;
1517     }
1518 //where
1519         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1520             return access(v, make.at(pos).Ident(v), null, false);
1521         }
1522 
1523     /** Construct a tree simulating the expression {@code C.this}.

1823     }
1824 
1825 /* ************************************************************************
1826  * Code for .class
1827  *************************************************************************/
1828 
1829     /** Return the symbol of a class to contain a cache of
1830      *  compiler-generated statics such as class$ and the
1831      *  $assertionsDisabled flag.  We create an anonymous nested class
1832      *  (unless one already exists) and return its symbol.  However,
1833      *  for backward compatibility in 1.4 and earlier we use the
1834      *  top-level class itself.
1835      */
1836     private ClassSymbol outerCacheClass() {
1837         ClassSymbol clazz = outermostClassDef.sym;
1838         Scope s = clazz.members();
1839         for (Symbol sym : s.getSymbols(NON_RECURSIVE))
1840             if (sym.kind == TYP &&
1841                 sym.name == names.empty &&
1842                 (sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
1843         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1844         return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
1845     }
1846 
1847     /** Create an attributed tree of the form left.name(). */
1848     private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
1849         Assert.checkNonNull(left.type);
1850         Symbol funcsym = lookupMethod(make_pos, name, left.type,
1851                                       TreeInfo.types(args));
1852         return make.App(make.Select(left, funcsym), args);
1853     }
1854 
1855     /** The tree simulating a T.class expression.
1856      *  @param clazz      The tree identifying type T.
1857      */
1858     private JCExpression classOf(JCTree clazz) {
1859         return classOfType(clazz.type, clazz.pos());
1860     }
1861 
1862     private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1863         switch (type.getTag()) {
1864         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1865         case DOUBLE: case BOOLEAN: case VOID:
1866             // replace with <BoxedClass>.TYPE
1867             ClassSymbol c = types.boxedClass(type);
1868             Symbol typeSym =
1869                 rs.accessBase(
1870                     rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR, null),
1871                     pos, c.type, names.TYPE, true);
1872             if (typeSym.kind == VAR)
1873                 ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
1874             return make.QualIdent(typeSym);
1875         case CLASS: case ARRAY:
1876                 VarSymbol sym = new VarSymbol(
1877                         STATIC | PUBLIC | FINAL, names._class,
1878                         syms.classType, type.tsym);
1879                 return make_at(pos).Select(make.Type(type), sym);
1880         default:
1881             throw new AssertionError();
1882         }
1883     }
1884 
1885 /* ************************************************************************
1886  * Code for enabling/disabling assertions.
1887  *************************************************************************/
1888 
1889     private ClassSymbol assertionsDisabledClassCache;
1890 
1891     /**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
1892      */
1893     private ClassSymbol assertionsDisabledClass() {
1894         if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
1895 
1896         // IDENTITY_TYPE will be interpreted as ACC_SUPER for older class files so we are fine
1897         assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
1898 
1899         return assertionsDisabledClassCache;
1900     }
1901 
1902     // This code is not particularly robust if the user has
1903     // previously declared a member named '$assertionsDisabled'.
1904     // The same faulty idiom also appears in the translation of
1905     // class literals above.  We should report an error if a
1906     // previous declaration is not synthetic.
1907 
1908     private JCExpression assertFlagTest(DiagnosticPosition pos) {
1909         // Outermost class may be either true class or an interface.
1910         ClassSymbol outermostClass = outermostClassDef.sym;
1911 
1912         //only classes can hold a non-public field, look for a usable one:
1913         ClassSymbol container = !currentClass.isInterface() ? currentClass :
1914                 assertionsDisabledClass();
1915 
1916         VarSymbol assertDisabledSym =
1917             (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,

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


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