Home » openjdk-7 » com.sun.tools » javac » comp » [javadoc | source]

    1   /*
    2    * Copyright (c) 1999, 2011, 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
   23    * questions.
   24    */
   25   
   26   package com.sun.tools.javac.comp;
   27   
   28   import java.util;
   29   
   30   import com.sun.tools.javac.code;
   31   import com.sun.tools.javac.jvm;
   32   import com.sun.tools.javac.main.RecognizedOptions.PkgInfo;
   33   import com.sun.tools.javac.tree;
   34   import com.sun.tools.javac.util;
   35   import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
   36   import com.sun.tools.javac.util.List;
   37   
   38   import com.sun.tools.javac.code.Symbol;
   39   import com.sun.tools.javac.tree.JCTree;
   40   import com.sun.tools.javac.code.Type;
   41   
   42   import com.sun.tools.javac.jvm.Target;
   43   
   44   import static com.sun.tools.javac.code.Flags.*;
   45   import static com.sun.tools.javac.code.Kinds.*;
   46   import static com.sun.tools.javac.code.TypeTags.*;
   47   import static com.sun.tools.javac.jvm.ByteCodes.*;
   48   
   49   /** This pass translates away some syntactic sugar: inner classes,
   50    *  class literals, assertions, foreach loops, etc.
   51    *
   52    *  <p><b>This is NOT part of any supported API.
   53    *  If you write code that depends on this, you do so at your own risk.
   54    *  This code and its internal interfaces are subject to change or
   55    *  deletion without notice.</b>
   56    */
   57   public class Lower extends TreeTranslator {
   58       protected static final Context.Key<Lower> lowerKey =
   59           new Context.Key<Lower>();
   60   
   61       public static Lower instance(Context context) {
   62           Lower instance = context.get(lowerKey);
   63           if (instance == null)
   64               instance = new Lower(context);
   65           return instance;
   66       }
   67   
   68       private Names names;
   69       private Log log;
   70       private Symtab syms;
   71       private Resolve rs;
   72       private Check chk;
   73       private Attr attr;
   74       private TreeMaker make;
   75       private DiagnosticPosition make_pos;
   76       private ClassWriter writer;
   77       private ClassReader reader;
   78       private ConstFold cfolder;
   79       private Target target;
   80       private Source source;
   81       private boolean allowEnums;
   82       private final Name dollarAssertionsDisabled;
   83       private final Name classDollar;
   84       private Types types;
   85       private boolean debugLower;
   86       private PkgInfo pkginfoOpt;
   87   
   88       protected Lower(Context context) {
   89           context.put(lowerKey, this);
   90           names = Names.instance(context);
   91           log = Log.instance(context);
   92           syms = Symtab.instance(context);
   93           rs = Resolve.instance(context);
   94           chk = Check.instance(context);
   95           attr = Attr.instance(context);
   96           make = TreeMaker.instance(context);
   97           writer = ClassWriter.instance(context);
   98           reader = ClassReader.instance(context);
   99           cfolder = ConstFold.instance(context);
  100           target = Target.instance(context);
  101           source = Source.instance(context);
  102           allowEnums = source.allowEnums();
  103           dollarAssertionsDisabled = names.
  104               fromString(target.syntheticNameChar() + "assertionsDisabled");
  105           classDollar = names.
  106               fromString("class" + target.syntheticNameChar());
  107   
  108           types = Types.instance(context);
  109           Options options = Options.instance(context);
  110           debugLower = options.isSet("debuglower");
  111           pkginfoOpt = PkgInfo.get(options);
  112       }
  113   
  114       /** The currently enclosing class.
  115        */
  116       ClassSymbol currentClass;
  117   
  118       /** A queue of all translated classes.
  119        */
  120       ListBuffer<JCTree> translated;
  121   
  122       /** Environment for symbol lookup, set by translateTopLevelClass.
  123        */
  124       Env<AttrContext> attrEnv;
  125   
  126       /** A hash table mapping syntax trees to their ending source positions.
  127        */
  128       Map<JCTree, Integer> endPositions;
  129   
  130   /**************************************************************************
  131    * Global mappings
  132    *************************************************************************/
  133   
  134       /** A hash table mapping local classes to their definitions.
  135        */
  136       Map<ClassSymbol, JCClassDecl> classdefs;
  137   
  138       /** A hash table mapping virtual accessed symbols in outer subclasses
  139        *  to the actually referred symbol in superclasses.
  140        */
  141       Map<Symbol,Symbol> actualSymbols;
  142   
  143       /** The current method definition.
  144        */
  145       JCMethodDecl currentMethodDef;
  146   
  147       /** The current method symbol.
  148        */
  149       MethodSymbol currentMethodSym;
  150   
  151       /** The currently enclosing outermost class definition.
  152        */
  153       JCClassDecl outermostClassDef;
  154   
  155       /** The currently enclosing outermost member definition.
  156        */
  157       JCTree outermostMemberDef;
  158   
  159       /** A navigator class for assembling a mapping from local class symbols
  160        *  to class definition trees.
  161        *  There is only one case; all other cases simply traverse down the tree.
  162        */
  163       class ClassMap extends TreeScanner {
  164   
  165           /** All encountered class defs are entered into classdefs table.
  166            */
  167           public void visitClassDef(JCClassDecl tree) {
  168               classdefs.put(tree.sym, tree);
  169               super.visitClassDef(tree);
  170           }
  171       }
  172       ClassMap classMap = new ClassMap();
  173   
  174       /** Map a class symbol to its definition.
  175        *  @param c    The class symbol of which we want to determine the definition.
  176        */
  177       JCClassDecl classDef(ClassSymbol c) {
  178           // First lookup the class in the classdefs table.
  179           JCClassDecl def = classdefs.get(c);
  180           if (def == null && outermostMemberDef != null) {
  181               // If this fails, traverse outermost member definition, entering all
  182               // local classes into classdefs, and try again.
  183               classMap.scan(outermostMemberDef);
  184               def = classdefs.get(c);
  185           }
  186           if (def == null) {
  187               // If this fails, traverse outermost class definition, entering all
  188               // local classes into classdefs, and try again.
  189               classMap.scan(outermostClassDef);
  190               def = classdefs.get(c);
  191           }
  192           return def;
  193       }
  194   
  195       /** A hash table mapping class symbols to lists of free variables.
  196        *  accessed by them. Only free variables of the method immediately containing
  197        *  a class are associated with that class.
  198        */
  199       Map<ClassSymbol,List<VarSymbol>> freevarCache;
  200   
  201       /** A navigator class for collecting the free variables accessed
  202        *  from a local class.
  203        *  There is only one case; all other cases simply traverse down the tree.
  204        */
  205       class FreeVarCollector extends TreeScanner {
  206   
  207           /** The owner of the local class.
  208            */
  209           Symbol owner;
  210   
  211           /** The local class.
  212            */
  213           ClassSymbol clazz;
  214   
  215           /** The list of owner's variables accessed from within the local class,
  216            *  without any duplicates.
  217            */
  218           List<VarSymbol> fvs;
  219   
  220           FreeVarCollector(ClassSymbol clazz) {
  221               this.clazz = clazz;
  222               this.owner = clazz.owner;
  223               this.fvs = List.nil();
  224           }
  225   
  226           /** Add free variable to fvs list unless it is already there.
  227            */
  228           private void addFreeVar(VarSymbol v) {
  229               for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail)
  230                   if (l.head == v) return;
  231               fvs = fvs.prepend(v);
  232           }
  233   
  234           /** Add all free variables of class c to fvs list
  235            *  unless they are already there.
  236            */
  237           private void addFreeVars(ClassSymbol c) {
  238               List<VarSymbol> fvs = freevarCache.get(c);
  239               if (fvs != null) {
  240                   for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
  241                       addFreeVar(l.head);
  242                   }
  243               }
  244           }
  245   
  246           /** If tree refers to a variable in owner of local class, add it to
  247            *  free variables list.
  248            */
  249           public void visitIdent(JCIdent tree) {
  250               result = tree;
  251               visitSymbol(tree.sym);
  252           }
  253           // where
  254           private void visitSymbol(Symbol _sym) {
  255               Symbol sym = _sym;
  256               if (sym.kind == VAR || sym.kind == MTH) {
  257                   while (sym != null && sym.owner != owner)
  258                       sym = proxies.lookup(proxyName(sym.name)).sym;
  259                   if (sym != null && sym.owner == owner) {
  260                       VarSymbol v = (VarSymbol)sym;
  261                       if (v.getConstValue() == null) {
  262                           addFreeVar(v);
  263                       }
  264                   } else {
  265                       if (outerThisStack.head != null &&
  266                           outerThisStack.head != _sym)
  267                           visitSymbol(outerThisStack.head);
  268                   }
  269               }
  270           }
  271   
  272           /** If tree refers to a class instance creation expression
  273            *  add all free variables of the freshly created class.
  274            */
  275           public void visitNewClass(JCNewClass tree) {
  276               ClassSymbol c = (ClassSymbol)tree.constructor.owner;
  277               addFreeVars(c);
  278               if (tree.encl == null &&
  279                   c.hasOuterInstance() &&
  280                   outerThisStack.head != null)
  281                   visitSymbol(outerThisStack.head);
  282               super.visitNewClass(tree);
  283           }
  284   
  285           /** If tree refers to a qualified this or super expression
  286            *  for anything but the current class, add the outer this
  287            *  stack as a free variable.
  288            */
  289           public void visitSelect(JCFieldAccess tree) {
  290               if ((tree.name == names._this || tree.name == names._super) &&
  291                   tree.selected.type.tsym != clazz &&
  292                   outerThisStack.head != null)
  293                   visitSymbol(outerThisStack.head);
  294               super.visitSelect(tree);
  295           }
  296   
  297           /** If tree refers to a superclass constructor call,
  298            *  add all free variables of the superclass.
  299            */
  300           public void visitApply(JCMethodInvocation tree) {
  301               if (TreeInfo.name(tree.meth) == names._super) {
  302                   addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner);
  303                   Symbol constructor = TreeInfo.symbol(tree.meth);
  304                   ClassSymbol c = (ClassSymbol)constructor.owner;
  305                   if (c.hasOuterInstance() &&
  306                       tree.meth.getTag() != JCTree.SELECT &&
  307                       outerThisStack.head != null)
  308                       visitSymbol(outerThisStack.head);
  309               }
  310               super.visitApply(tree);
  311           }
  312       }
  313   
  314       /** Return the variables accessed from within a local class, which
  315        *  are declared in the local class' owner.
  316        *  (in reverse order of first access).
  317        */
  318       List<VarSymbol> freevars(ClassSymbol c)  {
  319           if ((c.owner.kind & (VAR | MTH)) != 0) {
  320               List<VarSymbol> fvs = freevarCache.get(c);
  321               if (fvs == null) {
  322                   FreeVarCollector collector = new FreeVarCollector(c);
  323                   collector.scan(classDef(c));
  324                   fvs = collector.fvs;
  325                   freevarCache.put(c, fvs);
  326               }
  327               return fvs;
  328           } else {
  329               return List.nil();
  330           }
  331       }
  332   
  333       Map<TypeSymbol,EnumMapping> enumSwitchMap = new LinkedHashMap<TypeSymbol,EnumMapping>();
  334   
  335       EnumMapping mapForEnum(DiagnosticPosition pos, TypeSymbol enumClass) {
  336           EnumMapping map = enumSwitchMap.get(enumClass);
  337           if (map == null)
  338               enumSwitchMap.put(enumClass, map = new EnumMapping(pos, enumClass));
  339           return map;
  340       }
  341   
  342       /** This map gives a translation table to be used for enum
  343        *  switches.
  344        *
  345        *  <p>For each enum that appears as the type of a switch
  346        *  expression, we maintain an EnumMapping to assist in the
  347        *  translation, as exemplified by the following example:
  348        *
  349        *  <p>we translate
  350        *  <pre>
  351        *          switch(colorExpression) {
  352        *          case red: stmt1;
  353        *          case green: stmt2;
  354        *          }
  355        *  </pre>
  356        *  into
  357        *  <pre>
  358        *          switch(Outer$0.$EnumMap$Color[colorExpression.ordinal()]) {
  359        *          case 1: stmt1;
  360        *          case 2: stmt2
  361        *          }
  362        *  </pre>
  363        *  with the auxiliary table initialized as follows:
  364        *  <pre>
  365        *          class Outer$0 {
  366        *              synthetic final int[] $EnumMap$Color = new int[Color.values().length];
  367        *              static {
  368        *                  try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
  369        *                  try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
  370        *              }
  371        *          }
  372        *  </pre>
  373        *  class EnumMapping provides mapping data and support methods for this translation.
  374        */
  375       class EnumMapping {
  376           EnumMapping(DiagnosticPosition pos, TypeSymbol forEnum) {
  377               this.forEnum = forEnum;
  378               this.values = new LinkedHashMap<VarSymbol,Integer>();
  379               this.pos = pos;
  380               Name varName = names
  381                   .fromString(target.syntheticNameChar() +
  382                               "SwitchMap" +
  383                               target.syntheticNameChar() +
  384                               writer.xClassName(forEnum.type).toString()
  385                               .replace('/', '.')
  386                               .replace('.', target.syntheticNameChar()));
  387               ClassSymbol outerCacheClass = outerCacheClass();
  388               this.mapVar = new VarSymbol(STATIC | SYNTHETIC | FINAL,
  389                                           varName,
  390                                           new ArrayType(syms.intType, syms.arrayClass),
  391                                           outerCacheClass);
  392               enterSynthetic(pos, mapVar, outerCacheClass.members());
  393           }
  394   
  395           DiagnosticPosition pos = null;
  396   
  397           // the next value to use
  398           int next = 1; // 0 (unused map elements) go to the default label
  399   
  400           // the enum for which this is a map
  401           final TypeSymbol forEnum;
  402   
  403           // the field containing the map
  404           final VarSymbol mapVar;
  405   
  406           // the mapped values
  407           final Map<VarSymbol,Integer> values;
  408   
  409           JCLiteral forConstant(VarSymbol v) {
  410               Integer result = values.get(v);
  411               if (result == null)
  412                   values.put(v, result = next++);
  413               return make.Literal(result);
  414           }
  415   
  416           // generate the field initializer for the map
  417           void translate() {
  418               make.at(pos.getStartPosition());
  419               JCClassDecl owner = classDef((ClassSymbol)mapVar.owner);
  420   
  421               // synthetic static final int[] $SwitchMap$Color = new int[Color.values().length];
  422               MethodSymbol valuesMethod = lookupMethod(pos,
  423                                                        names.values,
  424                                                        forEnum.type,
  425                                                        List.<Type>nil());
  426               JCExpression size = make // Color.values().length
  427                   .Select(make.App(make.QualIdent(valuesMethod)),
  428                           syms.lengthVar);
  429               JCExpression mapVarInit = make
  430                   .NewArray(make.Type(syms.intType), List.of(size), null)
  431                   .setType(new ArrayType(syms.intType, syms.arrayClass));
  432   
  433               // try { $SwitchMap$Color[red.ordinal()] = 1; } catch (java.lang.NoSuchFieldError ex) {}
  434               ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
  435               Symbol ordinalMethod = lookupMethod(pos,
  436                                                   names.ordinal,
  437                                                   forEnum.type,
  438                                                   List.<Type>nil());
  439               List<JCCatch> catcher = List.<JCCatch>nil()
  440                   .prepend(make.Catch(make.VarDef(new VarSymbol(PARAMETER, names.ex,
  441                                                                 syms.noSuchFieldErrorType,
  442                                                                 syms.noSymbol),
  443                                                   null),
  444                                       make.Block(0, List.<JCStatement>nil())));
  445               for (Map.Entry<VarSymbol,Integer> e : values.entrySet()) {
  446                   VarSymbol enumerator = e.getKey();
  447                   Integer mappedValue = e.getValue();
  448                   JCExpression assign = make
  449                       .Assign(make.Indexed(mapVar,
  450                                            make.App(make.Select(make.QualIdent(enumerator),
  451                                                                 ordinalMethod))),
  452                               make.Literal(mappedValue))
  453                       .setType(syms.intType);
  454                   JCStatement exec = make.Exec(assign);
  455                   JCStatement _try = make.Try(make.Block(0, List.of(exec)), catcher, null);
  456                   stmts.append(_try);
  457               }
  458   
  459               owner.defs = owner.defs
  460                   .prepend(make.Block(STATIC, stmts.toList()))
  461                   .prepend(make.VarDef(mapVar, mapVarInit));
  462           }
  463       }
  464   
  465   
  466   /**************************************************************************
  467    * Tree building blocks
  468    *************************************************************************/
  469   
  470       /** Equivalent to make.at(pos.getStartPosition()) with side effect of caching
  471        *  pos as make_pos, for use in diagnostics.
  472        **/
  473       TreeMaker make_at(DiagnosticPosition pos) {
  474           make_pos = pos;
  475           return make.at(pos);
  476       }
  477   
  478       /** Make an attributed tree representing a literal. This will be an
  479        *  Ident node in the case of boolean literals, a Literal node in all
  480        *  other cases.
  481        *  @param type       The literal's type.
  482        *  @param value      The literal's value.
  483        */
  484       JCExpression makeLit(Type type, Object value) {
  485           return make.Literal(type.tag, value).setType(type.constType(value));
  486       }
  487   
  488       /** Make an attributed tree representing null.
  489        */
  490       JCExpression makeNull() {
  491           return makeLit(syms.botType, null);
  492       }
  493   
  494       /** Make an attributed class instance creation expression.
  495        *  @param ctype    The class type.
  496        *  @param args     The constructor arguments.
  497        */
  498       JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
  499           JCNewClass tree = make.NewClass(null,
  500               null, make.QualIdent(ctype.tsym), args, null);
  501           tree.constructor = rs.resolveConstructor(
  502               make_pos, attrEnv, ctype, TreeInfo.types(args), null, false, false);
  503           tree.type = ctype;
  504           return tree;
  505       }
  506   
  507       /** Make an attributed unary expression.
  508        *  @param optag    The operators tree tag.
  509        *  @param arg      The operator's argument.
  510        */
  511       JCUnary makeUnary(int optag, JCExpression arg) {
  512           JCUnary tree = make.Unary(optag, arg);
  513           tree.operator = rs.resolveUnaryOperator(
  514               make_pos, optag, attrEnv, arg.type);
  515           tree.type = tree.operator.type.getReturnType();
  516           return tree;
  517       }
  518   
  519       /** Make an attributed binary expression.
  520        *  @param optag    The operators tree tag.
  521        *  @param lhs      The operator's left argument.
  522        *  @param rhs      The operator's right argument.
  523        */
  524       JCBinary makeBinary(int optag, JCExpression lhs, JCExpression rhs) {
  525           JCBinary tree = make.Binary(optag, lhs, rhs);
  526           tree.operator = rs.resolveBinaryOperator(
  527               make_pos, optag, attrEnv, lhs.type, rhs.type);
  528           tree.type = tree.operator.type.getReturnType();
  529           return tree;
  530       }
  531   
  532       /** Make an attributed assignop expression.
  533        *  @param optag    The operators tree tag.
  534        *  @param lhs      The operator's left argument.
  535        *  @param rhs      The operator's right argument.
  536        */
  537       JCAssignOp makeAssignop(int optag, JCTree lhs, JCTree rhs) {
  538           JCAssignOp tree = make.Assignop(optag, lhs, rhs);
  539           tree.operator = rs.resolveBinaryOperator(
  540               make_pos, tree.getTag() - JCTree.ASGOffset, attrEnv, lhs.type, rhs.type);
  541           tree.type = lhs.type;
  542           return tree;
  543       }
  544   
  545       /** Convert tree into string object, unless it has already a
  546        *  reference type..
  547        */
  548       JCExpression makeString(JCExpression tree) {
  549           if (tree.type.tag >= CLASS) {
  550               return tree;
  551           } else {
  552               Symbol valueOfSym = lookupMethod(tree.pos(),
  553                                                names.valueOf,
  554                                                syms.stringType,
  555                                                List.of(tree.type));
  556               return make.App(make.QualIdent(valueOfSym), List.of(tree));
  557           }
  558       }
  559   
  560       /** Create an empty anonymous class definition and enter and complete
  561        *  its symbol. Return the class definition's symbol.
  562        *  and create
  563        *  @param flags    The class symbol's flags
  564        *  @param owner    The class symbol's owner
  565        */
  566       ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) {
  567           // Create class symbol.
  568           ClassSymbol c = reader.defineClass(names.empty, owner);
  569           c.flatname = chk.localClassName(c);
  570           c.sourcefile = owner.sourcefile;
  571           c.completer = null;
  572           c.members_field = new Scope(c);
  573           c.flags_field = flags;
  574           ClassType ctype = (ClassType) c.type;
  575           ctype.supertype_field = syms.objectType;
  576           ctype.interfaces_field = List.nil();
  577   
  578           JCClassDecl odef = classDef(owner);
  579   
  580           // Enter class symbol in owner scope and compiled table.
  581           enterSynthetic(odef.pos(), c, owner.members());
  582           chk.compiled.put(c.flatname, c);
  583   
  584           // Create class definition tree.
  585           JCClassDecl cdef = make.ClassDef(
  586               make.Modifiers(flags), names.empty,
  587               List.<JCTypeParameter>nil(),
  588               null, List.<JCExpression>nil(), List.<JCTree>nil());
  589           cdef.sym = c;
  590           cdef.type = c.type;
  591   
  592           // Append class definition tree to owner's definitions.
  593           odef.defs = odef.defs.prepend(cdef);
  594   
  595           return c;
  596       }
  597   
  598   /**************************************************************************
  599    * Symbol manipulation utilities
  600    *************************************************************************/
  601   
  602       /** Enter a synthetic symbol in a given scope, but complain if there was already one there.
  603        *  @param pos           Position for error reporting.
  604        *  @param sym           The symbol.
  605        *  @param s             The scope.
  606        */
  607       private void enterSynthetic(DiagnosticPosition pos, Symbol sym, Scope s) {
  608           s.enter(sym);
  609       }
  610   
  611       /** Create a fresh synthetic name within a given scope - the unique name is
  612        *  obtained by appending '$' chars at the end of the name until no match
  613        *  is found.
  614        *
  615        * @param name base name
  616        * @param s scope in which the name has to be unique
  617        * @return fresh synthetic name
  618        */
  619       private Name makeSyntheticName(Name name, Scope s) {
  620           do {
  621               name = name.append(
  622                       target.syntheticNameChar(),
  623                       names.empty);
  624           } while (lookupSynthetic(name, s) != null);
  625           return name;
  626       }
  627   
  628       /** Check whether synthetic symbols generated during lowering conflict
  629        *  with user-defined symbols.
  630        *
  631        *  @param translatedTrees lowered class trees
  632        */
  633       void checkConflicts(List<JCTree> translatedTrees) {
  634           for (JCTree t : translatedTrees) {
  635               t.accept(conflictsChecker);
  636           }
  637       }
  638   
  639       JCTree.Visitor conflictsChecker = new TreeScanner() {
  640   
  641           TypeSymbol currentClass;
  642   
  643           @Override
  644           public void visitMethodDef(JCMethodDecl that) {
  645               chk.checkConflicts(that.pos(), that.sym, currentClass);
  646               super.visitMethodDef(that);
  647           }
  648   
  649           @Override
  650           public void visitVarDef(JCVariableDecl that) {
  651               if (that.sym.owner.kind == TYP) {
  652                   chk.checkConflicts(that.pos(), that.sym, currentClass);
  653               }
  654               super.visitVarDef(that);
  655           }
  656   
  657           @Override
  658           public void visitClassDef(JCClassDecl that) {
  659               TypeSymbol prevCurrentClass = currentClass;
  660               currentClass = that.sym;
  661               try {
  662                   super.visitClassDef(that);
  663               }
  664               finally {
  665                   currentClass = prevCurrentClass;
  666               }
  667           }
  668       };
  669   
  670       /** Look up a synthetic name in a given scope.
  671        *  @param scope        The scope.
  672        *  @param name         The name.
  673        */
  674       private Symbol lookupSynthetic(Name name, Scope s) {
  675           Symbol sym = s.lookup(name).sym;
  676           return (sym==null || (sym.flags()&SYNTHETIC)==0) ? null : sym;
  677       }
  678   
  679       /** Look up a method in a given scope.
  680        */
  681       private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) {
  682           return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, null);
  683       }
  684   
  685       /** Look up a constructor.
  686        */
  687       private MethodSymbol lookupConstructor(DiagnosticPosition pos, Type qual, List<Type> args) {
  688           return rs.resolveInternalConstructor(pos, attrEnv, qual, args, null);
  689       }
  690   
  691       /** Look up a field.
  692        */
  693       private VarSymbol lookupField(DiagnosticPosition pos, Type qual, Name name) {
  694           return rs.resolveInternalField(pos, attrEnv, qual, name);
  695       }
  696   
  697       /** Anon inner classes are used as access constructor tags.
  698        * accessConstructorTag will use an existing anon class if one is available,
  699        * and synthethise a class (with makeEmptyClass) if one is not available.
  700        * However, there is a small possibility that an existing class will not
  701        * be generated as expected if it is inside a conditional with a constant
  702        * expression. If that is found to be the case, create an empty class here.
  703        */
  704       private void checkAccessConstructorTags() {
  705           for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
  706               ClassSymbol c = l.head;
  707               if (isTranslatedClassAvailable(c))
  708                   continue;
  709               // Create class definition tree.
  710               JCClassDecl cdef = make.ClassDef(
  711                   make.Modifiers(STATIC | SYNTHETIC), names.empty,
  712                   List.<JCTypeParameter>nil(),
  713                   null, List.<JCExpression>nil(), List.<JCTree>nil());
  714               cdef.sym = c;
  715               cdef.type = c.type;
  716               // add it to the list of classes to be generated
  717               translated.append(cdef);
  718           }
  719       }
  720       // where
  721       private boolean isTranslatedClassAvailable(ClassSymbol c) {
  722           for (JCTree tree: translated) {
  723               if (tree.getTag() == JCTree.CLASSDEF
  724                       && ((JCClassDecl) tree).sym == c) {
  725                   return true;
  726               }
  727           }
  728           return false;
  729       }
  730   
  731   /**************************************************************************
  732    * Access methods
  733    *************************************************************************/
  734   
  735       /** Access codes for dereferencing, assignment,
  736        *  and pre/post increment/decrement.
  737        *  Access codes for assignment operations are determined by method accessCode
  738        *  below.
  739        *
  740        *  All access codes for accesses to the current class are even.
  741        *  If a member of the superclass should be accessed instead (because
  742        *  access was via a qualified super), add one to the corresponding code
  743        *  for the current class, making the number odd.
  744        *  This numbering scheme is used by the backend to decide whether
  745        *  to issue an invokevirtual or invokespecial call.
  746        *
  747        *  @see Gen.visitSelect(Select tree)
  748        */
  749       private static final int
  750           DEREFcode = 0,
  751           ASSIGNcode = 2,
  752           PREINCcode = 4,
  753           PREDECcode = 6,
  754           POSTINCcode = 8,
  755           POSTDECcode = 10,
  756           FIRSTASGOPcode = 12;
  757   
  758       /** Number of access codes
  759        */
  760       private static final int NCODES = accessCode(ByteCodes.lushrl) + 2;
  761   
  762       /** A mapping from symbols to their access numbers.
  763        */
  764       private Map<Symbol,Integer> accessNums;
  765   
  766       /** A mapping from symbols to an array of access symbols, indexed by
  767        *  access code.
  768        */
  769       private Map<Symbol,MethodSymbol[]> accessSyms;
  770   
  771       /** A mapping from (constructor) symbols to access constructor symbols.
  772        */
  773       private Map<Symbol,MethodSymbol> accessConstrs;
  774   
  775       /** A list of all class symbols used for access constructor tags.
  776        */
  777       private List<ClassSymbol> accessConstrTags;
  778   
  779       /** A queue for all accessed symbols.
  780        */
  781       private ListBuffer<Symbol> accessed;
  782   
  783       /** Map bytecode of binary operation to access code of corresponding
  784        *  assignment operation. This is always an even number.
  785        */
  786       private static int accessCode(int bytecode) {
  787           if (ByteCodes.iadd <= bytecode && bytecode <= ByteCodes.lxor)
  788               return (bytecode - iadd) * 2 + FIRSTASGOPcode;
  789           else if (bytecode == ByteCodes.string_add)
  790               return (ByteCodes.lxor + 1 - iadd) * 2 + FIRSTASGOPcode;
  791           else if (ByteCodes.ishll <= bytecode && bytecode <= ByteCodes.lushrl)
  792               return (bytecode - ishll + ByteCodes.lxor + 2 - iadd) * 2 + FIRSTASGOPcode;
  793           else
  794               return -1;
  795       }
  796   
  797       /** return access code for identifier,
  798        *  @param tree     The tree representing the identifier use.
  799        *  @param enclOp   The closest enclosing operation node of tree,
  800        *                  null if tree is not a subtree of an operation.
  801        */
  802       private static int accessCode(JCTree tree, JCTree enclOp) {
  803           if (enclOp == null)
  804               return DEREFcode;
  805           else if (enclOp.getTag() == JCTree.ASSIGN &&
  806                    tree == TreeInfo.skipParens(((JCAssign) enclOp).lhs))
  807               return ASSIGNcode;
  808           else if (JCTree.PREINC <= enclOp.getTag() && enclOp.getTag() <= JCTree.POSTDEC &&
  809                    tree == TreeInfo.skipParens(((JCUnary) enclOp).arg))
  810               return (enclOp.getTag() - JCTree.PREINC) * 2 + PREINCcode;
  811           else if (JCTree.BITOR_ASG <= enclOp.getTag() && enclOp.getTag() <= JCTree.MOD_ASG &&
  812                    tree == TreeInfo.skipParens(((JCAssignOp) enclOp).lhs))
  813               return accessCode(((OperatorSymbol) ((JCAssignOp) enclOp).operator).opcode);
  814           else
  815               return DEREFcode;
  816       }
  817   
  818       /** Return binary operator that corresponds to given access code.
  819        */
  820       private OperatorSymbol binaryAccessOperator(int acode) {
  821           for (Scope.Entry e = syms.predefClass.members().elems;
  822                e != null;
  823                e = e.sibling) {
  824               if (e.sym instanceof OperatorSymbol) {
  825                   OperatorSymbol op = (OperatorSymbol)e.sym;
  826                   if (accessCode(op.opcode) == acode) return op;
  827               }
  828           }
  829           return null;
  830       }
  831   
  832       /** Return tree tag for assignment operation corresponding
  833        *  to given binary operator.
  834        */
  835       private static int treeTag(OperatorSymbol operator) {
  836           switch (operator.opcode) {
  837           case ByteCodes.ior: case ByteCodes.lor:
  838               return JCTree.BITOR_ASG;
  839           case ByteCodes.ixor: case ByteCodes.lxor:
  840               return JCTree.BITXOR_ASG;
  841           case ByteCodes.iand: case ByteCodes.land:
  842               return JCTree.BITAND_ASG;
  843           case ByteCodes.ishl: case ByteCodes.lshl:
  844           case ByteCodes.ishll: case ByteCodes.lshll:
  845               return JCTree.SL_ASG;
  846           case ByteCodes.ishr: case ByteCodes.lshr:
  847           case ByteCodes.ishrl: case ByteCodes.lshrl:
  848               return JCTree.SR_ASG;
  849           case ByteCodes.iushr: case ByteCodes.lushr:
  850           case ByteCodes.iushrl: case ByteCodes.lushrl:
  851               return JCTree.USR_ASG;
  852           case ByteCodes.iadd: case ByteCodes.ladd:
  853           case ByteCodes.fadd: case ByteCodes.dadd:
  854           case ByteCodes.string_add:
  855               return JCTree.PLUS_ASG;
  856           case ByteCodes.isub: case ByteCodes.lsub:
  857           case ByteCodes.fsub: case ByteCodes.dsub:
  858               return JCTree.MINUS_ASG;
  859           case ByteCodes.imul: case ByteCodes.lmul:
  860           case ByteCodes.fmul: case ByteCodes.dmul:
  861               return JCTree.MUL_ASG;
  862           case ByteCodes.idiv: case ByteCodes.ldiv:
  863           case ByteCodes.fdiv: case ByteCodes.ddiv:
  864               return JCTree.DIV_ASG;
  865           case ByteCodes.imod: case ByteCodes.lmod:
  866           case ByteCodes.fmod: case ByteCodes.dmod:
  867               return JCTree.MOD_ASG;
  868           default:
  869               throw new AssertionError();
  870           }
  871       }
  872   
  873       /** The name of the access method with number `anum' and access code `acode'.
  874        */
  875       Name accessName(int anum, int acode) {
  876           return names.fromString(
  877               "access" + target.syntheticNameChar() + anum + acode / 10 + acode % 10);
  878       }
  879   
  880       /** Return access symbol for a private or protected symbol from an inner class.
  881        *  @param sym        The accessed private symbol.
  882        *  @param tree       The accessing tree.
  883        *  @param enclOp     The closest enclosing operation node of tree,
  884        *                    null if tree is not a subtree of an operation.
  885        *  @param protAccess Is access to a protected symbol in another
  886        *                    package?
  887        *  @param refSuper   Is access via a (qualified) C.super?
  888        */
  889       MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree enclOp,
  890                                 boolean protAccess, boolean refSuper) {
  891           ClassSymbol accOwner = refSuper && protAccess
  892               // For access via qualified super (T.super.x), place the
  893               // access symbol on T.
  894               ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym
  895               // Otherwise pretend that the owner of an accessed
  896               // protected symbol is the enclosing class of the current
  897               // class which is a subclass of the symbol's owner.
  898               : accessClass(sym, protAccess, tree);
  899   
  900           Symbol vsym = sym;
  901           if (sym.owner != accOwner) {
  902               vsym = sym.clone(accOwner);
  903               actualSymbols.put(vsym, sym);
  904           }
  905   
  906           Integer anum              // The access number of the access method.
  907               = accessNums.get(vsym);
  908           if (anum == null) {
  909               anum = accessed.length();
  910               accessNums.put(vsym, anum);
  911               accessSyms.put(vsym, new MethodSymbol[NCODES]);
  912               accessed.append(vsym);
  913               // System.out.println("accessing " + vsym + " in " + vsym.location());
  914           }
  915   
  916           int acode;                // The access code of the access method.
  917           List<Type> argtypes;      // The argument types of the access method.
  918           Type restype;             // The result type of the access method.
  919           List<Type> thrown;        // The thrown exceptions of the access method.
  920           switch (vsym.kind) {
  921           case VAR:
  922               acode = accessCode(tree, enclOp);
  923               if (acode >= FIRSTASGOPcode) {
  924                   OperatorSymbol operator = binaryAccessOperator(acode);
  925                   if (operator.opcode == string_add)
  926                       argtypes = List.of(syms.objectType);
  927                   else
  928                       argtypes = operator.type.getParameterTypes().tail;
  929               } else if (acode == ASSIGNcode)
  930                   argtypes = List.of(vsym.erasure(types));
  931               else
  932                   argtypes = List.nil();
  933               restype = vsym.erasure(types);
  934               thrown = List.nil();
  935               break;
  936           case MTH:
  937               acode = DEREFcode;
  938               argtypes = vsym.erasure(types).getParameterTypes();
  939               restype = vsym.erasure(types).getReturnType();
  940               thrown = vsym.type.getThrownTypes();
  941               break;
  942           default:
  943               throw new AssertionError();
  944           }
  945   
  946           // For references via qualified super, increment acode by one,
  947           // making it odd.
  948           if (protAccess && refSuper) acode++;
  949   
  950           // Instance access methods get instance as first parameter.
  951           // For protected symbols this needs to be the instance as a member
  952           // of the type containing the accessed symbol, not the class
  953           // containing the access method.
  954           if ((vsym.flags() & STATIC) == 0) {
  955               argtypes = argtypes.prepend(vsym.owner.erasure(types));
  956           }
  957           MethodSymbol[] accessors = accessSyms.get(vsym);
  958           MethodSymbol accessor = accessors[acode];
  959           if (accessor == null) {
  960               accessor = new MethodSymbol(
  961                   STATIC | SYNTHETIC,
  962                   accessName(anum.intValue(), acode),
  963                   new MethodType(argtypes, restype, thrown, syms.methodClass),
  964                   accOwner);
  965               enterSynthetic(tree.pos(), accessor, accOwner.members());
  966               accessors[acode] = accessor;
  967           }
  968           return accessor;
  969       }
  970   
  971       /** The qualifier to be used for accessing a symbol in an outer class.
  972        *  This is either C.sym or C.this.sym, depending on whether or not
  973        *  sym is static.
  974        *  @param sym   The accessed symbol.
  975        */
  976       JCExpression accessBase(DiagnosticPosition pos, Symbol sym) {
  977           return (sym.flags() & STATIC) != 0
  978               ? access(make.at(pos.getStartPosition()).QualIdent(sym.owner))
  979               : makeOwnerThis(pos, sym, true);
  980       }
  981   
  982       /** Do we need an access method to reference private symbol?
  983        */
  984       boolean needsPrivateAccess(Symbol sym) {
  985           if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
  986               return false;
  987           } else if (sym.name == names.init && (sym.owner.owner.kind & (VAR | MTH)) != 0) {
  988               // private constructor in local class: relax protection
  989               sym.flags_field &= ~PRIVATE;
  990               return false;
  991           } else {
  992               return true;
  993           }
  994       }
  995   
  996       /** Do we need an access method to reference symbol in other package?
  997        */
  998       boolean needsProtectedAccess(Symbol sym, JCTree tree) {
  999           if ((sym.flags() & PROTECTED) == 0 ||
 1000               sym.owner.owner == currentClass.owner || // fast special case
 1001               sym.packge() == currentClass.packge())
 1002               return false;
 1003           if (!currentClass.isSubClass(sym.owner, types))
 1004               return true;
 1005           if ((sym.flags() & STATIC) != 0 ||
 1006               tree.getTag() != JCTree.SELECT ||
 1007               TreeInfo.name(((JCFieldAccess) tree).selected) == names._super)
 1008               return false;
 1009           return !((JCFieldAccess) tree).selected.type.tsym.isSubClass(currentClass, types);
 1010       }
 1011   
 1012       /** The class in which an access method for given symbol goes.
 1013        *  @param sym        The access symbol
 1014        *  @param protAccess Is access to a protected symbol in another
 1015        *                    package?
 1016        */
 1017       ClassSymbol accessClass(Symbol sym, boolean protAccess, JCTree tree) {
 1018           if (protAccess) {
 1019               Symbol qualifier = null;
 1020               ClassSymbol c = currentClass;
 1021               if (tree.getTag() == JCTree.SELECT && (sym.flags() & STATIC) == 0) {
 1022                   qualifier = ((JCFieldAccess) tree).selected.type.tsym;
 1023                   while (!qualifier.isSubClass(c, types)) {
 1024                       c = c.owner.enclClass();
 1025                   }
 1026                   return c;
 1027               } else {
 1028                   while (!c.isSubClass(sym.owner, types)) {
 1029                       c = c.owner.enclClass();
 1030                   }
 1031               }
 1032               return c;
 1033           } else {
 1034               // the symbol is private
 1035               return sym.owner.enclClass();
 1036           }
 1037       }
 1038   
 1039       /** Ensure that identifier is accessible, return tree accessing the identifier.
 1040        *  @param sym      The accessed symbol.
 1041        *  @param tree     The tree referring to the symbol.
 1042        *  @param enclOp   The closest enclosing operation node of tree,
 1043        *                  null if tree is not a subtree of an operation.
 1044        *  @param refSuper Is access via a (qualified) C.super?
 1045        */
 1046       JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean refSuper) {
 1047           // Access a free variable via its proxy, or its proxy's proxy
 1048           while (sym.kind == VAR && sym.owner.kind == MTH &&
 1049               sym.owner.enclClass() != currentClass) {
 1050               // A constant is replaced by its constant value.
 1051               Object cv = ((VarSymbol)sym).getConstValue();
 1052               if (cv != null) {
 1053                   make.at(tree.pos);
 1054                   return makeLit(sym.type, cv);
 1055               }
 1056               // Otherwise replace the variable by its proxy.
 1057               sym = proxies.lookup(proxyName(sym.name)).sym;
 1058               Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
 1059               tree = make.at(tree.pos).Ident(sym);
 1060           }
 1061           JCExpression base = (tree.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree).selected : null;
 1062           switch (sym.kind) {
 1063           case TYP:
 1064               if (sym.owner.kind != PCK) {
 1065                   // Convert type idents to
 1066                   // <flat name> or <package name> . <flat name>
 1067                   Name flatname = Convert.shortName(sym.flatName());
 1068                   while (base != null &&
 1069                          TreeInfo.symbol(base) != null &&
 1070                          TreeInfo.symbol(base).kind != PCK) {
 1071                       base = (base.getTag() == JCTree.SELECT)
 1072                           ? ((JCFieldAccess) base).selected
 1073                           : null;
 1074                   }
 1075                   if (tree.getTag() == JCTree.IDENT) {
 1076                       ((JCIdent) tree).name = flatname;
 1077                   } else if (base == null) {
 1078                       tree = make.at(tree.pos).Ident(sym);
 1079                       ((JCIdent) tree).name = flatname;
 1080                   } else {
 1081                       ((JCFieldAccess) tree).selected = base;
 1082                       ((JCFieldAccess) tree).name = flatname;
 1083                   }
 1084               }
 1085               break;
 1086           case MTH: case VAR:
 1087               if (sym.owner.kind == TYP) {
 1088   
 1089                   // Access methods are required for
 1090                   //  - private members,
 1091                   //  - protected members in a superclass of an
 1092                   //    enclosing class contained in another package.
 1093                   //  - all non-private members accessed via a qualified super.
 1094                   boolean protAccess = refSuper && !needsPrivateAccess(sym)
 1095                       || needsProtectedAccess(sym, tree);
 1096                   boolean accReq = protAccess || needsPrivateAccess(sym);
 1097   
 1098                   // A base has to be supplied for
 1099                   //  - simple identifiers accessing variables in outer classes.
 1100                   boolean baseReq =
 1101                       base == null &&
 1102                       sym.owner != syms.predefClass &&
 1103                       !sym.isMemberOf(currentClass, types);
 1104   
 1105                   if (accReq || baseReq) {
 1106                       make.at(tree.pos);
 1107   
 1108                       // Constants are replaced by their constant value.
 1109                       if (sym.kind == VAR) {
 1110                           Object cv = ((VarSymbol)sym).getConstValue();
 1111                           if (cv != null) return makeLit(sym.type, cv);
 1112                       }
 1113   
 1114                       // Private variables and methods are replaced by calls
 1115                       // to their access methods.
 1116                       if (accReq) {
 1117                           List<JCExpression> args = List.nil();
 1118                           if ((sym.flags() & STATIC) == 0) {
 1119                               // Instance access methods get instance
 1120                               // as first parameter.
 1121                               if (base == null)
 1122                                   base = makeOwnerThis(tree.pos(), sym, true);
 1123                               args = args.prepend(base);
 1124                               base = null;   // so we don't duplicate code
 1125                           }
 1126                           Symbol access = accessSymbol(sym, tree,
 1127                                                        enclOp, protAccess,
 1128                                                        refSuper);
 1129                           JCExpression receiver = make.Select(
 1130                               base != null ? base : make.QualIdent(access.owner),
 1131                               access);
 1132                           return make.App(receiver, args);
 1133   
 1134                       // Other accesses to members of outer classes get a
 1135                       // qualifier.
 1136                       } else if (baseReq) {
 1137                           return make.at(tree.pos).Select(
 1138                               accessBase(tree.pos(), sym), sym).setType(tree.type);
 1139                       }
 1140                   }
 1141               }
 1142           }
 1143           return tree;
 1144       }
 1145   
 1146       /** Ensure that identifier is accessible, return tree accessing the identifier.
 1147        *  @param tree     The identifier tree.
 1148        */
 1149       JCExpression access(JCExpression tree) {
 1150           Symbol sym = TreeInfo.symbol(tree);
 1151           return sym == null ? tree : access(sym, tree, null, false);
 1152       }
 1153   
 1154       /** Return access constructor for a private constructor,
 1155        *  or the constructor itself, if no access constructor is needed.
 1156        *  @param pos       The position to report diagnostics, if any.
 1157        *  @param constr    The private constructor.
 1158        */
 1159       Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) {
 1160           if (needsPrivateAccess(constr)) {
 1161               ClassSymbol accOwner = constr.owner.enclClass();
 1162               MethodSymbol aconstr = accessConstrs.get(constr);
 1163               if (aconstr == null) {
 1164                   List<Type> argtypes = constr.type.getParameterTypes();
 1165                   if ((accOwner.flags_field & ENUM) != 0)
 1166                       argtypes = argtypes
 1167                           .prepend(syms.intType)
 1168                           .prepend(syms.stringType);
 1169                   aconstr = new MethodSymbol(
 1170                       SYNTHETIC,
 1171                       names.init,
 1172                       new MethodType(
 1173                           argtypes.append(
 1174                               accessConstructorTag().erasure(types)),
 1175                           constr.type.getReturnType(),
 1176                           constr.type.getThrownTypes(),
 1177                           syms.methodClass),
 1178                       accOwner);
 1179                   enterSynthetic(pos, aconstr, accOwner.members());
 1180                   accessConstrs.put(constr, aconstr);
 1181                   accessed.append(constr);
 1182               }
 1183               return aconstr;
 1184           } else {
 1185               return constr;
 1186           }
 1187       }
 1188   
 1189       /** Return an anonymous class nested in this toplevel class.
 1190        */
 1191       ClassSymbol accessConstructorTag() {
 1192           ClassSymbol topClass = currentClass.outermostClass();
 1193           Name flatname = names.fromString("" + topClass.getQualifiedName() +
 1194                                            target.syntheticNameChar() +
 1195                                            "1");
 1196           ClassSymbol ctag = chk.compiled.get(flatname);
 1197           if (ctag == null)
 1198               ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass);
 1199           // keep a record of all tags, to verify that all are generated as required
 1200           accessConstrTags = accessConstrTags.prepend(ctag);
 1201           return ctag;
 1202       }
 1203   
 1204       /** Add all required access methods for a private symbol to enclosing class.
 1205        *  @param sym       The symbol.
 1206        */
 1207       void makeAccessible(Symbol sym) {
 1208           JCClassDecl cdef = classDef(sym.owner.enclClass());
 1209           if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
 1210           if (sym.name == names.init) {
 1211               cdef.defs = cdef.defs.prepend(
 1212                   accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
 1213           } else {
 1214               MethodSymbol[] accessors = accessSyms.get(sym);
 1215               for (int i = 0; i < NCODES; i++) {
 1216                   if (accessors[i] != null)
 1217                       cdef.defs = cdef.defs.prepend(
 1218                           accessDef(cdef.pos, sym, accessors[i], i));
 1219               }
 1220           }
 1221       }
 1222   
 1223       /** Construct definition of an access method.
 1224        *  @param pos        The source code position of the definition.
 1225        *  @param vsym       The private or protected symbol.
 1226        *  @param accessor   The access method for the symbol.
 1227        *  @param acode      The access code.
 1228        */
 1229       JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor, int acode) {
 1230   //      System.err.println("access " + vsym + " with " + accessor);//DEBUG
 1231           currentClass = vsym.owner.enclClass();
 1232           make.at(pos);
 1233           JCMethodDecl md = make.MethodDef(accessor, null);
 1234   
 1235           // Find actual symbol
 1236           Symbol sym = actualSymbols.get(vsym);
 1237           if (sym == null) sym = vsym;
 1238   
 1239           JCExpression ref;           // The tree referencing the private symbol.
 1240           List<JCExpression> args;    // Any additional arguments to be passed along.
 1241           if ((sym.flags() & STATIC) != 0) {
 1242               ref = make.Ident(sym);
 1243               args = make.Idents(md.params);
 1244           } else {
 1245               ref = make.Select(make.Ident(md.params.head), sym);
 1246               args = make.Idents(md.params.tail);
 1247           }
 1248           JCStatement stat;          // The statement accessing the private symbol.
 1249           if (sym.kind == VAR) {
 1250               // Normalize out all odd access codes by taking floor modulo 2:
 1251               int acode1 = acode - (acode & 1);
 1252   
 1253               JCExpression expr;      // The access method's return value.
 1254               switch (acode1) {
 1255               case DEREFcode:
 1256                   expr = ref;
 1257                   break;
 1258               case ASSIGNcode:
 1259                   expr = make.Assign(ref, args.head);
 1260                   break;
 1261               case PREINCcode: case POSTINCcode: case PREDECcode: case POSTDECcode:
 1262                   expr = makeUnary(
 1263                       ((acode1 - PREINCcode) >> 1) + JCTree.PREINC, ref);
 1264                   break;
 1265               default:
 1266                   expr = make.Assignop(
 1267                       treeTag(binaryAccessOperator(acode1)), ref, args.head);
 1268                   ((JCAssignOp) expr).operator = binaryAccessOperator(acode1);
 1269               }
 1270               stat = make.Return(expr.setType(sym.type));
 1271           } else {
 1272               stat = make.Call(make.App(ref, args));
 1273           }
 1274           md.body = make.Block(0, List.of(stat));
 1275   
 1276           // Make sure all parameters, result types and thrown exceptions
 1277           // are accessible.
 1278           for (List<JCVariableDecl> l = md.params; l.nonEmpty(); l = l.tail)
 1279               l.head.vartype = access(l.head.vartype);
 1280           md.restype = access(md.restype);
 1281           for (List<JCExpression> l = md.thrown; l.nonEmpty(); l = l.tail)
 1282               l.head = access(l.head);
 1283   
 1284           return md;
 1285       }
 1286   
 1287       /** Construct definition of an access constructor.
 1288        *  @param pos        The source code position of the definition.
 1289        *  @param constr     The private constructor.
 1290        *  @param accessor   The access method for the constructor.
 1291        */
 1292       JCTree accessConstructorDef(int pos, Symbol constr, MethodSymbol accessor) {
 1293           make.at(pos);
 1294           JCMethodDecl md = make.MethodDef(accessor,
 1295                                         accessor.externalType(types),
 1296                                         null);
 1297           JCIdent callee = make.Ident(names._this);
 1298           callee.sym = constr;
 1299           callee.type = constr.type;
 1300           md.body =
 1301               make.Block(0, List.<JCStatement>of(
 1302                   make.Call(
 1303                       make.App(
 1304                           callee,
 1305                           make.Idents(md.params.reverse().tail.reverse())))));
 1306           return md;
 1307       }
 1308   
 1309   /**************************************************************************
 1310    * Free variables proxies and this$n
 1311    *************************************************************************/
 1312   
 1313       /** A scope containing all free variable proxies for currently translated
 1314        *  class, as well as its this$n symbol (if needed).
 1315        *  Proxy scopes are nested in the same way classes are.
 1316        *  Inside a constructor, proxies and any this$n symbol are duplicated
 1317        *  in an additional innermost scope, where they represent the constructor
 1318        *  parameters.
 1319        */
 1320       Scope proxies;
 1321   
 1322       /** A scope containing all unnamed resource variables/saved
 1323        *  exception variables for translated TWR blocks
 1324        */
 1325       Scope twrVars;
 1326   
 1327       /** A stack containing the this$n field of the currently translated
 1328        *  classes (if needed) in innermost first order.
 1329        *  Inside a constructor, proxies and any this$n symbol are duplicated
 1330        *  in an additional innermost scope, where they represent the constructor
 1331        *  parameters.
 1332        */
 1333       List<VarSymbol> outerThisStack;
 1334   
 1335       /** The name of a free variable proxy.
 1336        */
 1337       Name proxyName(Name name) {
 1338           return names.fromString("val" + target.syntheticNameChar() + name);
 1339       }
 1340   
 1341       /** Proxy definitions for all free variables in given list, in reverse order.
 1342        *  @param pos        The source code position of the definition.
 1343        *  @param freevars   The free variables.
 1344        *  @param owner      The class in which the definitions go.
 1345        */
 1346       List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
 1347           long flags = FINAL | SYNTHETIC;
 1348           if (owner.kind == TYP &&
 1349               target.usePrivateSyntheticFields())
 1350               flags |= PRIVATE;
 1351           List<JCVariableDecl> defs = List.nil();
 1352           for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
 1353               VarSymbol v = l.head;
 1354               VarSymbol proxy = new VarSymbol(
 1355                   flags, proxyName(v.name), v.erasure(types), owner);
 1356               proxies.enter(proxy);
 1357               JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
 1358               vd.vartype = access(vd.vartype);
 1359               defs = defs.prepend(vd);
 1360           }
 1361           return defs;
 1362       }
 1363   
 1364       /** The name of a this$n field
 1365        *  @param type   The class referenced by the this$n field
 1366        */
 1367       Name outerThisName(Type type, Symbol owner) {
 1368           Type t = type.getEnclosingType();
 1369           int nestingLevel = 0;
 1370           while (t.tag == CLASS) {
 1371               t = t.getEnclosingType();
 1372               nestingLevel++;
 1373           }
 1374           Name result = names.fromString("this" + target.syntheticNameChar() + nestingLevel);
 1375           while (owner.kind == TYP && ((ClassSymbol)owner).members().lookup(result).scope != null)
 1376               result = names.fromString(result.toString() + target.syntheticNameChar());
 1377           return result;
 1378       }
 1379   
 1380       /** Definition for this$n field.
 1381        *  @param pos        The source code position of the definition.
 1382        *  @param owner      The class in which the definition goes.
 1383        */
 1384       JCVariableDecl outerThisDef(int pos, Symbol owner) {
 1385           long flags = FINAL | SYNTHETIC;
 1386           if (owner.kind == TYP &&
 1387               target.usePrivateSyntheticFields())
 1388               flags |= PRIVATE;
 1389           Type target = types.erasure(owner.enclClass().type.getEnclosingType());
 1390           VarSymbol outerThis = new VarSymbol(
 1391               flags, outerThisName(target, owner), target, owner);
 1392           outerThisStack = outerThisStack.prepend(outerThis);
 1393           JCVariableDecl vd = make.at(pos).VarDef(outerThis, null);
 1394           vd.vartype = access(vd.vartype);
 1395           return vd;
 1396       }
 1397   
 1398       /** Return a list of trees that load the free variables in given list,
 1399        *  in reverse order.
 1400        *  @param pos          The source code position to be used for the trees.
 1401        *  @param freevars     The list of free variables.
 1402        */
 1403       List<JCExpression> loadFreevars(DiagnosticPosition pos, List<VarSymbol> freevars) {
 1404           List<JCExpression> args = List.nil();
 1405           for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
 1406               args = args.prepend(loadFreevar(pos, l.head));
 1407           return args;
 1408       }
 1409   //where
 1410           JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
 1411               return access(v, make.at(pos).Ident(v), null, false);
 1412           }
 1413   
 1414       /** Construct a tree simulating the expression <C.this>.
 1415        *  @param pos           The source code position to be used for the tree.
 1416        *  @param c             The qualifier class.
 1417        */
 1418       JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
 1419           if (currentClass == c) {
 1420               // in this case, `this' works fine
 1421               return make.at(pos).This(c.erasure(types));
 1422           } else {
 1423               // need to go via this$n
 1424               return makeOuterThis(pos, c);
 1425           }
 1426       }
 1427   
 1428       /**
 1429        * Optionally replace a try statement with the desugaring of a
 1430        * try-with-resources statement.  The canonical desugaring of
 1431        *
 1432        * try ResourceSpecification
 1433        *   Block
 1434        *
 1435        * is
 1436        *
 1437        * {
 1438        *   final VariableModifiers_minus_final R #resource = Expression;
 1439        *   Throwable #primaryException = null;
 1440        *
 1441        *   try ResourceSpecificationtail
 1442        *     Block
 1443        *   catch (Throwable #t) {
 1444        *     #primaryException = t;
 1445        *     throw #t;
 1446        *   } finally {
 1447        *     if (#resource != null) {
 1448        *       if (#primaryException != null) {
 1449        *         try {
 1450        *           #resource.close();
 1451        *         } catch(Throwable #suppressedException) {
 1452        *           #primaryException.addSuppressed(#suppressedException);
 1453        *         }
 1454        *       } else {
 1455        *         #resource.close();
 1456        *       }
 1457        *     }
 1458        *   }
 1459        *
 1460        * @param tree  The try statement to inspect.
 1461        * @return A a desugared try-with-resources tree, or the original
 1462        * try block if there are no resources to manage.
 1463        */
 1464       JCTree makeTwrTry(JCTry tree) {
 1465           make_at(tree.pos());
 1466           twrVars = twrVars.dup();
 1467           JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0);
 1468           if (tree.catchers.isEmpty() && tree.finalizer == null)
 1469               result = translate(twrBlock);
 1470           else
 1471               result = translate(make.Try(twrBlock, tree.catchers, tree.finalizer));
 1472           twrVars = twrVars.leave();
 1473           return result;
 1474       }
 1475   
 1476       private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {
 1477           if (resources.isEmpty())
 1478               return block;
 1479   
 1480           // Add resource declaration or expression to block statements
 1481           ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
 1482           JCTree resource = resources.head;
 1483           JCExpression expr = null;
 1484           if (resource instanceof JCVariableDecl) {
 1485               JCVariableDecl var = (JCVariableDecl) resource;
 1486               expr = make.Ident(var.sym).setType(resource.type);
 1487               stats.add(var);
 1488           } else {
 1489               Assert.check(resource instanceof JCExpression);
 1490               VarSymbol syntheticTwrVar =
 1491               new VarSymbol(SYNTHETIC | FINAL,
 1492                             makeSyntheticName(names.fromString("twrVar" +
 1493                                              depth), twrVars),
 1494                             (resource.type.tag == TypeTags.BOT) ?
 1495                             syms.autoCloseableType : resource.type,
 1496                             currentMethodSym);
 1497               twrVars.enter(syntheticTwrVar);
 1498               JCVariableDecl syntheticTwrVarDecl =
 1499                   make.VarDef(syntheticTwrVar, (JCExpression)resource);
 1500               expr = (JCExpression)make.Ident(syntheticTwrVar);
 1501               stats.add(syntheticTwrVarDecl);
 1502           }
 1503   
 1504           // Add primaryException declaration
 1505           VarSymbol primaryException =
 1506               new VarSymbol(SYNTHETIC,
 1507                             makeSyntheticName(names.fromString("primaryException" +
 1508                             depth), twrVars),
 1509                             syms.throwableType,
 1510                             currentMethodSym);
 1511           twrVars.enter(primaryException);
 1512           JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
 1513           stats.add(primaryExceptionTreeDecl);
 1514   
 1515           // Create catch clause that saves exception and then rethrows it
 1516           VarSymbol param =
 1517               new VarSymbol(FINAL|SYNTHETIC,
 1518                             names.fromString("t" +
 1519                                              target.syntheticNameChar()),
 1520                             syms.throwableType,
 1521                             currentMethodSym);
 1522           JCVariableDecl paramTree = make.VarDef(param, null);
 1523           JCStatement assign = make.Assignment(primaryException, make.Ident(param));
 1524           JCStatement rethrowStat = make.Throw(make.Ident(param));
 1525           JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
 1526           JCCatch catchClause = make.Catch(paramTree, catchBlock);
 1527   
 1528           int oldPos = make.pos;
 1529           make.at(TreeInfo.endPos(block));
 1530           JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr);
 1531           make.at(oldPos);
 1532           JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
 1533                                     List.<JCCatch>of(catchClause),
 1534                                     finallyClause);
 1535           stats.add(outerTry);
 1536           return make.Block(0L, stats.toList());
 1537       }
 1538   
 1539       private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) {
 1540           // primaryException.addSuppressed(catchException);
 1541           VarSymbol catchException =
 1542               new VarSymbol(0, make.paramName(2),
 1543                             syms.throwableType,
 1544                             currentMethodSym);
 1545           JCStatement addSuppressionStatement =
 1546               make.Exec(makeCall(make.Ident(primaryException),
 1547                                  names.addSuppressed,
 1548                                  List.<JCExpression>of(make.Ident(catchException))));
 1549   
 1550           // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
 1551           JCBlock tryBlock =
 1552               make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
 1553           JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
 1554           JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
 1555           List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
 1556           JCTry tryTree = make.Try(tryBlock, catchClauses, null);
 1557   
 1558           // if (primaryException != null) {try...} else resourceClose;
 1559           JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),
 1560                                           tryTree,
 1561                                           makeResourceCloseInvocation(resource));
 1562   
 1563           // if (#resource != null) { if (primaryException ...  }
 1564           return make.Block(0L,
 1565                             List.<JCStatement>of(make.If(makeNonNullCheck(resource),
 1566                                                          closeIfStatement,
 1567                                                          null)));
 1568       }
 1569   
 1570       private JCStatement makeResourceCloseInvocation(JCExpression resource) {
 1571           // create resource.close() method invocation
 1572           JCExpression resourceClose = makeCall(resource,
 1573                                                 names.close,
 1574                                                 List.<JCExpression>nil());
 1575           return make.Exec(resourceClose);
 1576       }
 1577   
 1578       private JCExpression makeNonNullCheck(JCExpression expression) {
 1579           return makeBinary(JCTree.NE, expression, makeNull());
 1580       }
 1581   
 1582       /** Construct a tree that represents the outer instance
 1583        *  <C.this>. Never pick the current `this'.
 1584        *  @param pos           The source code position to be used for the tree.
 1585        *  @param c             The qualifier class.
 1586        */
 1587       JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
 1588           List<VarSymbol> ots = outerThisStack;
 1589           if (ots.isEmpty()) {
 1590               log.error(pos, "no.encl.instance.of.type.in.scope", c);
 1591               Assert.error();
 1592               return makeNull();
 1593           }
 1594           VarSymbol ot = ots.head;
 1595           JCExpression tree = access(make.at(pos).Ident(ot));
 1596           TypeSymbol otc = ot.type.tsym;
 1597           while (otc != c) {
 1598               do {
 1599                   ots = ots.tail;
 1600                   if (ots.isEmpty()) {
 1601                       log.error(pos,
 1602                                 "no.encl.instance.of.type.in.scope",
 1603                                 c);
 1604                       Assert.error(); // should have been caught in Attr
 1605                       return tree;
 1606                   }
 1607                   ot = ots.head;
 1608               } while (ot.owner != otc);
 1609               if (otc.owner.kind != PCK && !otc.hasOuterInstance()) {
 1610                   chk.earlyRefError(pos, c);
 1611                   Assert.error(); // should have been caught in Attr
 1612                   return makeNull();
 1613               }
 1614               tree = access(make.at(pos).Select(tree, ot));
 1615               otc = ot.type.tsym;
 1616           }
 1617           return tree;
 1618       }
 1619   
 1620       /** Construct a tree that represents the closest outer instance
 1621        *  <C.this> such that the given symbol is a member of C.
 1622        *  @param pos           The source code position to be used for the tree.
 1623        *  @param sym           The accessed symbol.
 1624        *  @param preciseMatch  should we accept a type that is a subtype of
 1625        *                       sym's owner, even if it doesn't contain sym
 1626        *                       due to hiding, overriding, or non-inheritance
 1627        *                       due to protection?
 1628        */
 1629       JCExpression makeOwnerThis(DiagnosticPosition pos, Symbol sym, boolean preciseMatch) {
 1630           Symbol c = sym.owner;
 1631           if (preciseMatch ? sym.isMemberOf(currentClass, types)
 1632                            : currentClass.isSubClass(sym.owner, types)) {
 1633               // in this case, `this' works fine
 1634               return make.at(pos).This(c.erasure(types));
 1635           } else {
 1636               // need to go via this$n
 1637               return makeOwnerThisN(pos, sym, preciseMatch);
 1638           }
 1639       }
 1640   
 1641       /**
 1642        * Similar to makeOwnerThis but will never pick "this".
 1643        */
 1644       JCExpression makeOwnerThisN(DiagnosticPosition pos, Symbol sym, boolean preciseMatch) {
 1645           Symbol c = sym.owner;
 1646           List<VarSymbol> ots = outerThisStack;
 1647           if (ots.isEmpty()) {
 1648               log.error(pos, "no.encl.instance.of.type.in.scope", c);
 1649               Assert.error();
 1650               return makeNull();
 1651           }
 1652           VarSymbol ot = ots.head;
 1653           JCExpression tree = access(make.at(pos).Ident(ot));
 1654           TypeSymbol otc = ot.type.tsym;
 1655           while (!(preciseMatch ? sym.isMemberOf(otc, types) : otc.isSubClass(sym.owner, types))) {
 1656               do {
 1657                   ots = ots.tail;
 1658                   if (ots.isEmpty()) {
 1659                       log.error(pos,
 1660                           "no.encl.instance.of.type.in.scope",
 1661                           c);
 1662                       Assert.error();
 1663                       return tree;
 1664                   }
 1665                   ot = ots.head;
 1666               } while (ot.owner != otc);
 1667               tree = access(make.at(pos).Select(tree, ot));
 1668               otc = ot.type.tsym;
 1669           }
 1670           return tree;
 1671       }
 1672   
 1673       /** Return tree simulating the assignment <this.name = name>, where
 1674        *  name is the name of a free variable.
 1675        */
 1676       JCStatement initField(int pos, Name name) {
 1677           Scope.Entry e = proxies.lookup(name);
 1678           Symbol rhs = e.sym;
 1679           Assert.check(rhs.owner.kind == MTH);
 1680           Symbol lhs = e.next().sym;
 1681           Assert.check(rhs.owner.owner == lhs.owner);
 1682           make.at(pos);
 1683           return
 1684               make.Exec(
 1685                   make.Assign(
 1686                       make.Select(make.This(lhs.owner.erasure(types)), lhs),
 1687                       make.Ident(rhs)).setType(lhs.erasure(types)));
 1688       }
 1689   
 1690       /** Return tree simulating the assignment <this.this$n = this$n>.
 1691        */
 1692       JCStatement initOuterThis(int pos) {
 1693           VarSymbol rhs = outerThisStack.head;
 1694           Assert.check(rhs.owner.kind == MTH);
 1695           VarSymbol lhs = outerThisStack.tail.head;
 1696           Assert.check(rhs.owner.owner == lhs.owner);
 1697           make.at(pos);
 1698           return
 1699               make.Exec(
 1700                   make.Assign(
 1701                       make.Select(make.This(lhs.owner.erasure(types)), lhs),
 1702                       make.Ident(rhs)).setType(lhs.erasure(types)));
 1703       }
 1704   
 1705   /**************************************************************************
 1706    * Code for .class
 1707    *************************************************************************/
 1708   
 1709       /** Return the symbol of a class to contain a cache of
 1710        *  compiler-generated statics such as class$ and the
 1711        *  $assertionsDisabled flag.  We create an anonymous nested class
 1712        *  (unless one already exists) and return its symbol.  However,
 1713        *  for backward compatibility in 1.4 and earlier we use the
 1714        *  top-level class itself.
 1715        */
 1716       private ClassSymbol outerCacheClass() {
 1717           ClassSymbol clazz = outermostClassDef.sym;
 1718           if ((clazz.flags() & INTERFACE) == 0 &&
 1719               !target.useInnerCacheClass()) return clazz;
 1720           Scope s = clazz.members();
 1721           for (Scope.Entry e = s.elems; e != null; e = e.sibling)
 1722               if (e.sym.kind == TYP &&
 1723                   e.sym.name == names.empty &&
 1724                   (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym;
 1725           return makeEmptyClass(STATIC | SYNTHETIC, clazz);
 1726       }
 1727   
 1728       /** Return symbol for "class$" method. If there is no method definition
 1729        *  for class$, construct one as follows:
 1730        *
 1731        *    class class$(String x0) {
 1732        *      try {
 1733        *        return Class.forName(x0);
 1734        *      } catch (ClassNotFoundException x1) {
 1735        *        throw new NoClassDefFoundError(x1.getMessage());
 1736        *      }
 1737        *    }
 1738        */
 1739       private MethodSymbol classDollarSym(DiagnosticPosition pos) {
 1740           ClassSymbol outerCacheClass = outerCacheClass();
 1741           MethodSymbol classDollarSym =
 1742               (MethodSymbol)lookupSynthetic(classDollar,
 1743                                             outerCacheClass.members());
 1744           if (classDollarSym == null) {
 1745               classDollarSym = new MethodSymbol(
 1746                   STATIC | SYNTHETIC,
 1747                   classDollar,
 1748                   new MethodType(
 1749                       List.of(syms.stringType),
 1750                       types.erasure(syms.classType),
 1751                       List.<Type>nil(),
 1752                       syms.methodClass),
 1753                   outerCacheClass);
 1754               enterSynthetic(pos, classDollarSym, outerCacheClass.members());
 1755   
 1756               JCMethodDecl md = make.MethodDef(classDollarSym, null);
 1757               try {
 1758                   md.body = classDollarSymBody(pos, md);
 1759               } catch (CompletionFailure ex) {
 1760                   md.body = make.Block(0, List.<JCStatement>nil());
 1761                   chk.completionError(pos, ex);
 1762               }
 1763               JCClassDecl outerCacheClassDef = classDef(outerCacheClass);
 1764               outerCacheClassDef.defs = outerCacheClassDef.defs.prepend(md);
 1765           }
 1766           return classDollarSym;
 1767       }
 1768   
 1769       /** Generate code for class$(String name). */
 1770       JCBlock classDollarSymBody(DiagnosticPosition pos, JCMethodDecl md) {
 1771           MethodSymbol classDollarSym = md.sym;
 1772           ClassSymbol outerCacheClass = (ClassSymbol)classDollarSym.owner;
 1773   
 1774           JCBlock returnResult;
 1775   
 1776           // in 1.4.2 and above, we use
 1777           // Class.forName(String name, boolean init, ClassLoader loader);
 1778           // which requires we cache the current loader in cl$
 1779           if (target.classLiteralsNoInit()) {
 1780               // clsym = "private static ClassLoader cl$"
 1781               VarSymbol clsym = new VarSymbol(STATIC|SYNTHETIC,
 1782                                               names.fromString("cl" + target.syntheticNameChar()),
 1783                                               syms.classLoaderType,
 1784                                               outerCacheClass);
 1785               enterSynthetic(pos, clsym, outerCacheClass.members());
 1786   
 1787               // emit "private static ClassLoader cl$;"
 1788               JCVariableDecl cldef = make.VarDef(clsym, null);
 1789               JCClassDecl outerCacheClassDef = classDef(outerCacheClass);
 1790               outerCacheClassDef.defs = outerCacheClassDef.defs.prepend(cldef);
 1791   
 1792               // newcache := "new cache$1[0]"
 1793               JCNewArray newcache = make.
 1794                   NewArray(make.Type(outerCacheClass.type),
 1795                            List.<JCExpression>of(make.Literal(INT, 0).setType(syms.intType)),
 1796                            null);
 1797               newcache.type = new ArrayType(types.erasure(outerCacheClass.type),
 1798                                             syms.arrayClass);
 1799   
 1800               // forNameSym := java.lang.Class.forName(
 1801               //     String s,boolean init,ClassLoader loader)
 1802               Symbol forNameSym = lookupMethod(make_pos, names.forName,
 1803                                                types.erasure(syms.classType),
 1804                                                List.of(syms.stringType,
 1805                                                        syms.booleanType,
 1806                                                        syms.classLoaderType));
 1807               // clvalue := "(cl$ == null) ?
 1808               // $newcache.getClass().getComponentType().getClassLoader() : cl$"
 1809               JCExpression clvalue =
 1810                   make.Conditional(
 1811                       makeBinary(JCTree.EQ, make.Ident(clsym), makeNull()),
 1812                       make.Assign(
 1813                           make.Ident(clsym),
 1814                           makeCall(
 1815                               makeCall(makeCall(newcache,
 1816                                                 names.getClass,
 1817                                                 List.<JCExpression>nil()),
 1818                                        names.getComponentType,
 1819                                        List.<JCExpression>nil()),
 1820                               names.getClassLoader,
 1821                               List.<JCExpression>nil())).setType(syms.classLoaderType),
 1822                       make.Ident(clsym)).setType(syms.classLoaderType);
 1823   
 1824               // returnResult := "{ return Class.forName(param1, false, cl$); }"
 1825               List<JCExpression> args = List.of(make.Ident(md.params.head.sym),
 1826                                                 makeLit(syms.booleanType, 0),
 1827                                                 clvalue);
 1828               returnResult = make.
 1829                   Block(0, List.<JCStatement>of(make.
 1830                                 Call(make. // return
 1831                                      App(make.
 1832                                          Ident(forNameSym), args))));
 1833           } else {
 1834               // forNameSym := java.lang.Class.forName(String s)
 1835               Symbol forNameSym = lookupMethod(make_pos,
 1836                                                names.forName,
 1837                                                types.erasure(syms.classType),
 1838                                                List.of(syms.stringType));
 1839               // returnResult := "{ return Class.forName(param1); }"
 1840               returnResult = make.
 1841                   Block(0, List.of(make.
 1842                             Call(make. // return
 1843                                 App(make.
 1844                                     QualIdent(forNameSym),
 1845                                     List.<JCExpression>of(make.
 1846                                                           Ident(md.params.
 1847                                                                 head.sym))))));
 1848           }
 1849   
 1850           // catchParam := ClassNotFoundException e1
 1851           VarSymbol catchParam =
 1852               new VarSymbol(0, make.paramName(1),
 1853                             syms.classNotFoundExceptionType,
 1854                             classDollarSym);
 1855   
 1856           JCStatement rethrow;
 1857           if (target.hasInitCause()) {
 1858               // rethrow = "throw new NoClassDefFoundError().initCause(e);
 1859               JCTree throwExpr =
 1860                   makeCall(makeNewClass(syms.noClassDefFoundErrorType,
 1861                                         List.<JCExpression>nil()),
 1862                            names.initCause,
 1863                            List.<JCExpression>of(make.Ident(catchParam)));
 1864               rethrow = make.Throw(throwExpr);
 1865           } else {
 1866               // getMessageSym := ClassNotFoundException.getMessage()
 1867               Symbol getMessageSym = lookupMethod(make_pos,
 1868                                                   names.getMessage,
 1869                                                   syms.classNotFoundExceptionType,
 1870                                                   List.<Type>nil());
 1871               // rethrow = "throw new NoClassDefFoundError(e.getMessage());"
 1872               rethrow = make.
 1873                   Throw(makeNewClass(syms.noClassDefFoundErrorType,
 1874                             List.<JCExpression>of(make.App(make.Select(make.Ident(catchParam),
 1875                                                                        getMessageSym),
 1876                                                            List.<JCExpression>nil()))));
 1877           }
 1878   
 1879           // rethrowStmt := "( $rethrow )"
 1880           JCBlock rethrowStmt = make.Block(0, List.of(rethrow));
 1881   
 1882           // catchBlock := "catch ($catchParam) $rethrowStmt"
 1883           JCCatch catchBlock = make.Catch(make.VarDef(catchParam, null),
 1884                                         rethrowStmt);
 1885   
 1886           // tryCatch := "try $returnResult $catchBlock"
 1887           JCStatement tryCatch = make.Try(returnResult,
 1888                                           List.of(catchBlock), null);
 1889   
 1890           return make.Block(0, List.of(tryCatch));
 1891       }
 1892       // where
 1893           /** Create an attributed tree of the form left.name(). */
 1894           private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
 1895               Assert.checkNonNull(left.type);
 1896               Symbol funcsym = lookupMethod(make_pos, name, left.type,
 1897                                             TreeInfo.types(args));
 1898               return make.App(make.Select(left, funcsym), args);
 1899           }
 1900   
 1901       /** The Name Of The variable to cache T.class values.
 1902        *  @param sig      The signature of type T.
 1903        */
 1904       private Name cacheName(String sig) {
 1905           StringBuffer buf = new StringBuffer();
 1906           if (sig.startsWith("[")) {
 1907               buf = buf.append("array");
 1908               while (sig.startsWith("[")) {
 1909                   buf = buf.append(target.syntheticNameChar());
 1910                   sig = sig.substring(1);
 1911               }
 1912               if (sig.startsWith("L")) {
 1913                   sig = sig.substring(0, sig.length() - 1);
 1914               }
 1915           } else {
 1916               buf = buf.append("class" + target.syntheticNameChar());
 1917           }
 1918           buf = buf.append(sig.replace('.', target.syntheticNameChar()));
 1919           return names.fromString(buf.toString());
 1920       }
 1921   
 1922       /** The variable symbol that caches T.class values.
 1923        *  If none exists yet, create a definition.
 1924        *  @param sig      The signature of type T.
 1925        *  @param pos      The position to report diagnostics, if any.
 1926        */
 1927       private VarSymbol cacheSym(DiagnosticPosition pos, String sig) {
 1928           ClassSymbol outerCacheClass = outerCacheClass();
 1929           Name cname = cacheName(sig);
 1930           VarSymbol cacheSym =
 1931               (VarSymbol)lookupSynthetic(cname, outerCacheClass.members());
 1932           if (cacheSym == null) {
 1933               cacheSym = new VarSymbol(
 1934                   STATIC | SYNTHETIC, cname, types.erasure(syms.classType), outerCacheClass);
 1935               enterSynthetic(pos, cacheSym, outerCacheClass.members());
 1936   
 1937               JCVariableDecl cacheDef = make.VarDef(cacheSym, null);
 1938               JCClassDecl outerCacheClassDef = classDef(outerCacheClass);
 1939               outerCacheClassDef.defs = outerCacheClassDef.defs.prepend(cacheDef);
 1940           }
 1941           return cacheSym;
 1942       }
 1943   
 1944       /** The tree simulating a T.class expression.
 1945        *  @param clazz      The tree identifying type T.
 1946        */
 1947       private JCExpression classOf(JCTree clazz) {
 1948           return classOfType(clazz.type, clazz.pos());
 1949       }
 1950   
 1951       private JCExpression classOfType(Type type, DiagnosticPosition pos) {
 1952           switch (type.tag) {
 1953           case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
 1954           case DOUBLE: case BOOLEAN: case VOID:
 1955               // replace with <BoxedClass>.TYPE
 1956               ClassSymbol c = types.boxedClass(type);
 1957               Symbol typeSym =
 1958                   rs.access(
 1959                       rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR),
 1960                       pos, c.type, names.TYPE, true);
 1961               if (typeSym.kind == VAR)
 1962                   ((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
 1963               return make.QualIdent(typeSym);
 1964           case CLASS: case ARRAY:
 1965               if (target.hasClassLiterals()) {
 1966                   VarSymbol sym = new VarSymbol(
 1967                           STATIC | PUBLIC | FINAL, names._class,
 1968                           syms.classType, type.tsym);
 1969                   return make_at(pos).Select(make.Type(type), sym);
 1970               }
 1971               // replace with <cache == null ? cache = class$(tsig) : cache>
 1972               // where
 1973               //  - <tsig>  is the type signature of T,
 1974               //  - <cache> is the cache variable for tsig.
 1975               String sig =
 1976                   writer.xClassName(type).toString().replace('/', '.');
 1977               Symbol cs = cacheSym(pos, sig);
 1978               return make_at(pos).Conditional(
 1979                   makeBinary(JCTree.EQ, make.Ident(cs), makeNull()),
 1980                   make.Assign(
 1981                       make.Ident(cs),
 1982                       make.App(
 1983                           make.Ident(classDollarSym(pos)),
 1984                           List.<JCExpression>of(make.Literal(CLASS, sig)
 1985                                                 .setType(syms.stringType))))
 1986                   .setType(types.erasure(syms.classType)),
 1987                   make.Ident(cs)).setType(types.erasure(syms.classType));
 1988           default:
 1989               throw new AssertionError();
 1990           }
 1991       }
 1992   
 1993   /**************************************************************************
 1994    * Code for enabling/disabling assertions.
 1995    *************************************************************************/
 1996   
 1997       // This code is not particularly robust if the user has
 1998       // previously declared a member named '$assertionsDisabled'.
 1999       // The same faulty idiom also appears in the translation of
 2000       // class literals above.  We should report an error if a
 2001       // previous declaration is not synthetic.
 2002   
 2003       private JCExpression assertFlagTest(DiagnosticPosition pos) {
 2004           // Outermost class may be either true class or an interface.
 2005           ClassSymbol outermostClass = outermostClassDef.sym;
 2006   
 2007           // note that this is a class, as an interface can't contain a statement.
 2008           ClassSymbol container = currentClass;
 2009   
 2010           VarSymbol assertDisabledSym =
 2011               (VarSymbol)lookupSynthetic(dollarAssertionsDisabled,
 2012                                          container.members());
 2013           if (assertDisabledSym == null) {
 2014               assertDisabledSym =
 2015                   new VarSymbol(STATIC | FINAL | SYNTHETIC,
 2016                                 dollarAssertionsDisabled,
 2017                                 syms.booleanType,
 2018                                 container);
 2019               enterSynthetic(pos, assertDisabledSym, container.members());
 2020               Symbol desiredAssertionStatusSym = lookupMethod(pos,
 2021                                                               names.desiredAssertionStatus,
 2022                                                               types.erasure(syms.classType),
 2023                                                               List.<Type>nil());
 2024               JCClassDecl containerDef = classDef(container);
 2025               make_at(containerDef.pos());
 2026               JCExpression notStatus = makeUnary(JCTree.NOT, make.App(make.Select(
 2027                       classOfType(types.erasure(outermostClass.type),
 2028                                   containerDef.pos()),
 2029                       desiredAssertionStatusSym)));
 2030               JCVariableDecl assertDisabledDef = make.VarDef(assertDisabledSym,
 2031                                                      notStatus);
 2032               containerDef.defs = containerDef.defs.prepend(assertDisabledDef);
 2033           }
 2034           make_at(pos);
 2035           return makeUnary(JCTree.NOT, make.Ident(assertDisabledSym));
 2036       }
 2037   
 2038   
 2039   /**************************************************************************
 2040    * Building blocks for let expressions
 2041    *************************************************************************/
 2042   
 2043       interface TreeBuilder {
 2044           JCTree build(JCTree arg);
 2045       }
 2046   
 2047       /** Construct an expression using the builder, with the given rval
 2048        *  expression as an argument to the builder.  However, the rval
 2049        *  expression must be computed only once, even if used multiple
 2050        *  times in the result of the builder.  We do that by
 2051        *  constructing a "let" expression that saves the rvalue into a
 2052        *  temporary variable and then uses the temporary variable in
 2053        *  place of the expression built by the builder.  The complete
 2054        *  resulting expression is of the form
 2055        *  <pre>
 2056        *    (let <b>TYPE</b> <b>TEMP</b> = <b>RVAL</b>;
 2057        *     in (<b>BUILDER</b>(<b>TEMP</b>)))
 2058        *  </pre>
 2059        *  where <code><b>TEMP</b></code> is a newly declared variable
 2060        *  in the let expression.
 2061        */
 2062       JCTree abstractRval(JCTree rval, Type type, TreeBuilder builder) {
 2063           rval = TreeInfo.skipParens(rval);
 2064           switch (rval.getTag()) {
 2065           case JCTree.LITERAL:
 2066               return builder.build(rval);
 2067           case JCTree.IDENT:
 2068               JCIdent id = (JCIdent) rval;
 2069               if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == MTH)
 2070                   return builder.build(rval);
 2071           }
 2072           VarSymbol var =
 2073               new VarSymbol(FINAL|SYNTHETIC,
 2074                             names.fromString(
 2075                                             target.syntheticNameChar()
 2076                                             + "" + rval.hashCode()),
 2077                                         type,
 2078                                         currentMethodSym);
 2079           rval = convert(rval,type);
 2080           JCVariableDecl def = make.VarDef(var, (JCExpression)rval); // XXX cast
 2081           JCTree built = builder.build(make.Ident(var));
 2082           JCTree res = make.LetExpr(def, built);
 2083           res.type = built.type;
 2084           return res;
 2085       }
 2086   
 2087       // same as above, with the type of the temporary variable computed
 2088       JCTree abstractRval(JCTree rval, TreeBuilder builder) {
 2089           return abstractRval(rval, rval.type, builder);
 2090       }
 2091   
 2092       // same as above, but for an expression that may be used as either
 2093       // an rvalue or an lvalue.  This requires special handling for
 2094       // Select expressions, where we place the left-hand-side of the
 2095       // select in a temporary, and for Indexed expressions, where we
 2096       // place both the indexed expression and the index value in temps.
 2097       JCTree abstractLval(JCTree lval, final TreeBuilder builder) {
 2098           lval = TreeInfo.skipParens(lval);
 2099           switch (lval.getTag()) {
 2100           case JCTree.IDENT:
 2101               return builder.build(lval);
 2102           case JCTree.SELECT: {
 2103               final JCFieldAccess s = (JCFieldAccess)lval;
 2104               JCTree selected = TreeInfo.skipParens(s.selected);
 2105               Symbol lid = TreeInfo.symbol(s.selected);
 2106               if (lid != null && lid.kind == TYP) return builder.build(lval);
 2107               return abstractRval(s.selected, new TreeBuilder() {
 2108                       public JCTree build(final JCTree selected) {
 2109                           return builder.build(make.Select((JCExpression)selected, s.sym));
 2110                       }
 2111                   });
 2112           }
 2113           case JCTree.INDEXED: {
 2114               final JCArrayAccess i = (JCArrayAccess)lval;
 2115               return abstractRval(i.indexed, new TreeBuilder() {
 2116                       public JCTree build(final JCTree indexed) {
 2117                           return abstractRval(i.index, syms.intType, new TreeBuilder() {
 2118                                   public JCTree build(final JCTree index) {
 2119                                       JCTree newLval = make.Indexed((JCExpression)indexed,
 2120                                                                   (JCExpression)index);
 2121                                       newLval.setType(i.type);
 2122                                       return builder.build(newLval);
 2123                                   }
 2124                               });
 2125                       }
 2126                   });
 2127           }
 2128           case JCTree.TYPECAST: {
 2129               return abstractLval(((JCTypeCast)lval).expr, builder);
 2130           }
 2131           }
 2132           throw new AssertionError(lval);
 2133       }
 2134   
 2135       // evaluate and discard the first expression, then evaluate the second.
 2136       JCTree makeComma(final JCTree expr1, final JCTree expr2) {
 2137           return abstractRval(expr1, new TreeBuilder() {
 2138                   public JCTree build(final JCTree discarded) {
 2139                       return expr2;
 2140                   }
 2141               });
 2142       }
 2143   
 2144   /**************************************************************************
 2145    * Translation methods
 2146    *************************************************************************/
 2147   
 2148       /** Visitor argument: enclosing operator node.
 2149        */
 2150       private JCExpression enclOp;
 2151   
 2152       /** Visitor method: Translate a single node.
 2153        *  Attach the source position from the old tree to its replacement tree.
 2154        */
 2155       public <T extends JCTree> T translate(T tree) {
 2156           if (tree == null) {
 2157               return null;
 2158           } else {
 2159               make_at(tree.pos());
 2160               T result = super.translate(tree);
 2161               if (endPositions != null && result != tree) {
 2162                   Integer endPos = endPositions.remove(tree);
 2163                   if (endPos != null) endPositions.put(result, endPos);
 2164               }
 2165               return result;
 2166           }
 2167       }
 2168   
 2169       /** Visitor method: Translate a single node, boxing or unboxing if needed.
 2170        */
 2171       public <T extends JCTree> T translate(T tree, Type type) {
 2172           return (tree == null) ? null : boxIfNeeded(translate(tree), type);
 2173       }
 2174   
 2175       /** Visitor method: Translate tree.
 2176        */
 2177       public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
 2178           JCExpression prevEnclOp = this.enclOp;
 2179           this.enclOp = enclOp;
 2180           T res = translate(tree);
 2181           this.enclOp = prevEnclOp;
 2182           return res;
 2183       }
 2184   
 2185       /** Visitor method: Translate list of trees.
 2186        */
 2187       public <T extends JCTree> List<T> translate(List<T> trees, JCExpression enclOp) {
 2188           JCExpression prevEnclOp = this.enclOp;
 2189           this.enclOp = enclOp;
 2190           List<T> res = translate(trees);
 2191           this.enclOp = prevEnclOp;
 2192           return res;
 2193       }
 2194   
 2195       /** Visitor method: Translate list of trees.
 2196        */
 2197       public <T extends JCTree> List<T> translate(List<T> trees, Type type) {
 2198           if (trees == null) return null;
 2199           for (List<T> l = trees; l.nonEmpty(); l = l.tail)
 2200               l.head = translate(l.head, type);
 2201           return trees;
 2202       }
 2203   
 2204       public void visitTopLevel(JCCompilationUnit tree) {
 2205           if (needPackageInfoClass(tree)) {
 2206               Name name = names.package_info;
 2207               long flags = Flags.ABSTRACT | Flags.INTERFACE;
 2208               if (target.isPackageInfoSynthetic())
 2209                   // package-info is marked SYNTHETIC in JDK 1.6 and later releases
 2210                   flags = flags | Flags.SYNTHETIC;
 2211               JCClassDecl packageAnnotationsClass
 2212                   = make.ClassDef(make.Modifiers(flags,
 2213                                                  tree.packageAnnotations),
 2214                                   name, List.<JCTypeParameter>nil(),
 2215                                   null, List.<JCExpression>nil(), List.<JCTree>nil());
 2216               ClassSymbol c = tree.packge.package_info;
 2217               c.flags_field |= flags;
 2218               c.attributes_field = tree.packge.attributes_field;
 2219               ClassType ctype = (ClassType) c.type;
 2220               ctype.supertype_field = syms.objectType;
 2221               ctype.interfaces_field = List.nil();
 2222               packageAnnotationsClass.sym = c;
 2223   
 2224               translated.append(packageAnnotationsClass);
 2225           }
 2226       }
 2227       // where
 2228       private boolean needPackageInfoClass(JCCompilationUnit tree) {
 2229           switch (pkginfoOpt) {
 2230               case ALWAYS:
 2231                   return true;
 2232               case LEGACY:
 2233                   return tree.packageAnnotations.nonEmpty();
 2234               case NONEMPTY:
 2235                   for (Attribute.Compound a: tree.packge.attributes_field) {
 2236                       Attribute.RetentionPolicy p = types.getRetention(a);
 2237                       if (p != Attribute.RetentionPolicy.SOURCE)
 2238                           return true;
 2239                   }
 2240                   return false;
 2241           }
 2242           throw new AssertionError();
 2243       }
 2244   
 2245       public void visitClassDef(JCClassDecl tree) {
 2246           ClassSymbol currentClassPrev = currentClass;
 2247           MethodSymbol currentMethodSymPrev = currentMethodSym;
 2248           currentClass = tree.sym;
 2249           currentMethodSym = null;
 2250           classdefs.put(currentClass, tree);
 2251   
 2252           proxies = proxies.dup(currentClass);
 2253           List<VarSymbol> prevOuterThisStack = outerThisStack;
 2254   
 2255           // If this is an enum definition
 2256           if ((tree.mods.flags & ENUM) != 0 &&
 2257               (types.supertype(currentClass.type).tsym.flags() & ENUM) == 0)
 2258               visitEnumDef(tree);
 2259   
 2260           // If this is a nested class, define a this$n field for
 2261           // it and add to proxies.
 2262           JCVariableDecl otdef = null;
 2263           if (currentClass.hasOuterInstance())
 2264               otdef = outerThisDef(tree.pos, currentClass);
 2265   
 2266           // If this is a local class, define proxies for all its free variables.
 2267           List<JCVariableDecl> fvdefs = freevarDefs(
 2268               tree.pos, freevars(currentClass), currentClass);
 2269   
 2270           // Recursively translate superclass, interfaces.
 2271           tree.extending = translate(tree.extending);
 2272           tree.implementing = translate(tree.implementing);
 2273   
 2274           // Recursively translate members, taking into account that new members
 2275           // might be created during the translation and prepended to the member
 2276           // list `tree.defs'.
 2277           List<JCTree> seen = List.nil();
 2278           while (tree.defs != seen) {
 2279               List<JCTree> unseen = tree.defs;
 2280               for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
 2281                   JCTree outermostMemberDefPrev = outermostMemberDef;
 2282                   if (outermostMemberDefPrev == null) outermostMemberDef = l.head;
 2283                   l.head = translate(l.head);
 2284                   outermostMemberDef = outermostMemberDefPrev;
 2285               }
 2286               seen = unseen;
 2287           }
 2288   
 2289           // Convert a protected modifier to public, mask static modifier.
 2290           if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
 2291           tree.mods.flags &= ClassFlags;
 2292   
 2293           // Convert name to flat representation, replacing '.' by '$'.
 2294           tree.name = Convert.shortName(currentClass.flatName());
 2295   
 2296           // Add this$n and free variables proxy definitions to class.
 2297           for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
 2298               tree.defs = tree.defs.prepend(l.head);
 2299               enterSynthetic(tree.pos(), l.head.sym, currentClass.members());
 2300           }
 2301           if (currentClass.hasOuterInstance()) {
 2302               tree.defs = tree.defs.prepend(otdef);
 2303               enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
 2304           }
 2305   
 2306           proxies = proxies.leave();
 2307           outerThisStack = prevOuterThisStack;
 2308   
 2309           // Append translated tree to `translated' queue.
 2310           translated.append(tree);
 2311   
 2312           currentClass = currentClassPrev;
 2313           currentMethodSym = currentMethodSymPrev;
 2314   
 2315           // Return empty block {} as a placeholder for an inner class.
 2316           result = make_at(tree.pos()).Block(0, List.<JCStatement>nil());
 2317       }
 2318   
 2319       /** Translate an enum class. */
 2320       private void visitEnumDef(JCClassDecl tree) {
 2321           make_at(tree.pos());
 2322   
 2323           // add the supertype, if needed
 2324           if (tree.extending == null)
 2325               tree.extending = make.Type(types.supertype(tree.type));
 2326   
 2327           // classOfType adds a cache field to tree.defs unless
 2328           // target.hasClassLiterals().
 2329           JCExpression e_class = classOfType(tree.sym.type, tree.pos()).
 2330               setType(types.erasure(syms.classType));
 2331   
 2332           // process each enumeration constant, adding implicit constructor parameters
 2333           int nextOrdinal = 0;
 2334           ListBuffer<JCExpression> values = new ListBuffer<JCExpression>();
 2335           ListBuffer<JCTree> enumDefs = new ListBuffer<JCTree>();
 2336           ListBuffer<JCTree> otherDefs = new ListBuffer<JCTree>();
 2337           for (List<JCTree> defs = tree.defs;
 2338                defs.nonEmpty();
 2339                defs=defs.tail) {
 2340               if (defs.head.getTag() == JCTree.VARDEF && (((JCVariableDecl) defs.head).mods.flags & ENUM) != 0) {
 2341                   JCVariableDecl var = (JCVariableDecl)defs.head;
 2342                   visitEnumConstantDef(var, nextOrdinal++);
 2343                   values.append(make.QualIdent(var.sym));
 2344                   enumDefs.append(var);
 2345               } else {
 2346                   otherDefs.append(defs.head);
 2347               }
 2348           }
 2349   
 2350           // private static final T[] #VALUES = { a, b, c };
 2351           Name valuesName = names.fromString(target.syntheticNameChar() + "VALUES");
 2352           while (tree.sym.members().lookup(valuesName).scope != null) // avoid name clash
 2353               valuesName = names.fromString(valuesName + "" + target.syntheticNameChar());
 2354           Type arrayType = new ArrayType(types.erasure(tree.type), syms.arrayClass);
 2355           VarSymbol valuesVar = new VarSymbol(PRIVATE|FINAL|STATIC|SYNTHETIC,
 2356                                               valuesName,
 2357                                               arrayType,
 2358                                               tree.type.tsym);
 2359           JCNewArray newArray = make.NewArray(make.Type(types.erasure(tree.type)),
 2360                                             List.<JCExpression>nil(),
 2361                                             values.toList());
 2362           newArray.type = arrayType;
 2363           enumDefs.append(make.VarDef(valuesVar, newArray));
 2364           tree.sym.members().enter(valuesVar);
 2365   
 2366           Symbol valuesSym = lookupMethod(tree.pos(), names.values,
 2367                                           tree.type, List.<Type>nil());
 2368           List<JCStatement> valuesBody;
 2369           if (useClone()) {
 2370               // return (T[]) $VALUES.clone();
 2371               JCTypeCast valuesResult =
 2372                   make.TypeCast(valuesSym.type.getReturnType(),
 2373                                 make.App(make.Select(make.Ident(valuesVar),
 2374                                                      syms.arrayCloneMethod)));
 2375               valuesBody = List.<JCStatement>of(make.Return(valuesResult));
 2376           } else {
 2377               // template: T[] $result = new T[$values.length];
 2378               Name resultName = names.fromString(target.syntheticNameChar() + "result");
 2379               while (tree.sym.members().lookup(resultName).scope != null) // avoid name clash
 2380                   resultName = names.fromString(resultName + "" + target.syntheticNameChar());
 2381               VarSymbol resultVar = new VarSymbol(FINAL|SYNTHETIC,
 2382                                                   resultName,
 2383                                                   arrayType,
 2384                                                   valuesSym);
 2385               JCNewArray resultArray = make.NewArray(make.Type(types.erasure(tree.type)),
 2386                                     List.of(make.Select(make.Ident(valuesVar), syms.lengthVar)),
 2387                                     null);
 2388               resultArray.type = arrayType;
 2389               JCVariableDecl decl = make.VarDef(resultVar, resultArray);
 2390   
 2391               // template: System.arraycopy($VALUES, 0, $result, 0, $VALUES.length);
 2392               if (systemArraycopyMethod == null) {
 2393                   systemArraycopyMethod =
 2394                       new MethodSymbol(PUBLIC | STATIC,
 2395                                        names.fromString("arraycopy"),
 2396                                        new MethodType(List.<Type>of(syms.objectType,
 2397                                                               syms.intType,
 2398                                                               syms.objectType,
 2399                                                               syms.intType,
 2400                                                               syms.intType),
 2401                                                       syms.voidType,
 2402                                                       List.<Type>nil(),
 2403                                                       syms.methodClass),
 2404                                        syms.systemType.tsym);
 2405               }
 2406               JCStatement copy =
 2407                   make.Exec(make.App(make.Select(make.Ident(syms.systemType.tsym),
 2408                                                  systemArraycopyMethod),
 2409                             List.of(make.Ident(valuesVar), make.Literal(0),
 2410                                     make.Ident(resultVar), make.Literal(0),
 2411                                     make.Select(make.Ident(valuesVar), syms.lengthVar))));
 2412   
 2413               // template: return $result;
 2414               JCStatement ret = make.Return(make.Ident(resultVar));
 2415               valuesBody = List.<JCStatement>of(decl, copy, ret);
 2416           }
 2417   
 2418           JCMethodDecl valuesDef =
 2419                make.MethodDef((MethodSymbol)valuesSym, make.Block(0, valuesBody));
 2420   
 2421           enumDefs.append(valuesDef);
 2422   
 2423           if (debugLower)
 2424               System.err.println(tree.sym + ".valuesDef = " + valuesDef);
 2425   
 2426           /** The template for the following code is:
 2427            *
 2428            *     public static E valueOf(String name) {
 2429            *         return (E)Enum.valueOf(E.class, name);
 2430            *     }
 2431            *
 2432            *  where E is tree.sym
 2433            */
 2434           MethodSymbol valueOfSym = lookupMethod(tree.pos(),
 2435                            names.valueOf,
 2436                            tree.sym.type,
 2437                            List.of(syms.stringType));
 2438           Assert.check((valueOfSym.flags() & STATIC) != 0);
 2439           VarSymbol nameArgSym = valueOfSym.params.head;
 2440           JCIdent nameVal = make.Ident(nameArgSym);
 2441           JCStatement enum_ValueOf =
 2442               make.Return(make.TypeCast(tree.sym.type,
 2443                                         makeCall(make.Ident(syms.enumSym),
 2444                                                  names.valueOf,
 2445                                                  List.of(e_class, nameVal))));
 2446           JCMethodDecl valueOf = make.MethodDef(valueOfSym,
 2447                                              make.Block(0, List.of(enum_ValueOf)));
 2448           nameVal.sym = valueOf.params.head.sym;
 2449           if (debugLower)
 2450               System.err.println(tree.sym + ".valueOf = " + valueOf);
 2451           enumDefs.append(valueOf);
 2452   
 2453           enumDefs.appendList(otherDefs.toList());
 2454           tree.defs = enumDefs.toList();
 2455   
 2456           // Add the necessary members for the EnumCompatibleMode
 2457           if (target.compilerBootstrap(tree.sym)) {
 2458               addEnumCompatibleMembers(tree);
 2459           }
 2460       }
 2461           // where
 2462           private MethodSymbol systemArraycopyMethod;
 2463           private boolean useClone() {
 2464               try {
 2465                   Scope.Entry e = syms.objectType.tsym.members().lookup(names.clone);
 2466                   return (e.sym != null);
 2467               }
 2468               catch (CompletionFailure e) {
 2469                   return false;
 2470               }
 2471           }
 2472   
 2473       /** Translate an enumeration constant and its initializer. */
 2474       private void visitEnumConstantDef(JCVariableDecl var, int ordinal) {
 2475           JCNewClass varDef = (JCNewClass)var.init;
 2476           varDef.args = varDef.args.
 2477               prepend(makeLit(syms.intType, ordinal)).
 2478               prepend(makeLit(syms.stringType, var.name.toString()));
 2479       }
 2480   
 2481       public void visitMethodDef(JCMethodDecl tree) {
 2482           if (tree.name == names.init && (currentClass.flags_field&ENUM) != 0) {
 2483               // Add "String $enum$name, int $enum$ordinal" to the beginning of the
 2484               // argument list for each constructor of an enum.
 2485               JCVariableDecl nameParam = make_at(tree.pos()).
 2486                   Param(names.fromString(target.syntheticNameChar() +
 2487                                          "enum" + target.syntheticNameChar() + "name"),
 2488                         syms.stringType, tree.sym);
 2489               nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
 2490   
 2491               JCVariableDecl ordParam = make.
 2492                   Param(names.fromString(target.syntheticNameChar() +
 2493                                          "enum" + target.syntheticNameChar() +
 2494                                          "ordinal"),
 2495                         syms.intType, tree.sym);
 2496               ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
 2497   
 2498               tree.params = tree.params.prepend(ordParam).prepend(nameParam);
 2499   
 2500               MethodSymbol m = tree.sym;
 2501               Type olderasure = m.erasure(types);
 2502               m.erasure_field = new MethodType(
 2503                   olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
 2504                   olderasure.getReturnType(),
 2505                   olderasure.getThrownTypes(),
 2506                   syms.methodClass);
 2507   
 2508               if (target.compilerBootstrap(m.owner)) {
 2509                   // Initialize synthetic name field
 2510                   Symbol nameVarSym = lookupSynthetic(names.fromString("$name"),
 2511                                                       tree.sym.owner.members());
 2512                   JCIdent nameIdent = make.Ident(nameParam.sym);
 2513                   JCIdent id1 = make.Ident(nameVarSym);
 2514                   JCAssign newAssign = make.Assign(id1, nameIdent);
 2515                   newAssign.type = id1.type;
 2516                   JCExpressionStatement nameAssign = make.Exec(newAssign);
 2517                   nameAssign.type = id1.type;
 2518                   tree.body.stats = tree.body.stats.prepend(nameAssign);
 2519   
 2520                   // Initialize synthetic ordinal field
 2521                   Symbol ordinalVarSym = lookupSynthetic(names.fromString("$ordinal"),
 2522                                                          tree.sym.owner.members());
 2523                   JCIdent ordIdent = make.Ident(ordParam.sym);
 2524                   id1 = make.Ident(ordinalVarSym);
 2525                   newAssign = make.Assign(id1, ordIdent);
 2526                   newAssign.type = id1.type;
 2527                   JCExpressionStatement ordinalAssign = make.Exec(newAssign);
 2528                   ordinalAssign.type = id1.type;
 2529                   tree.body.stats = tree.body.stats.prepend(ordinalAssign);
 2530               }
 2531           }
 2532   
 2533           JCMethodDecl prevMethodDef = currentMethodDef;
 2534           MethodSymbol prevMethodSym = currentMethodSym;
 2535           try {
 2536               currentMethodDef = tree;
 2537               currentMethodSym = tree.sym;
 2538               visitMethodDefInternal(tree);
 2539           } finally {
 2540               currentMethodDef = prevMethodDef;
 2541               currentMethodSym = prevMethodSym;
 2542           }
 2543       }
 2544       //where
 2545       private void visitMethodDefInternal(JCMethodDecl tree) {
 2546           if (tree.name == names.init &&
 2547               (currentClass.isInner() ||
 2548                (currentClass.owner.kind & (VAR | MTH)) != 0)) {
 2549               // We are seeing a constructor of an inner class.
 2550               MethodSymbol m = tree.sym;
 2551   
 2552               // Push a new proxy scope for constructor parameters.
 2553               // and create definitions for any this$n and proxy parameters.
 2554               proxies = proxies.dup(m);
 2555               List<VarSymbol> prevOuterThisStack = outerThisStack;
 2556               List<VarSymbol> fvs = freevars(currentClass);
 2557               JCVariableDecl otdef = null;
 2558               if (currentClass.hasOuterInstance())
 2559                   otdef = outerThisDef(tree.pos, m);
 2560               List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m);
 2561   
 2562               // Recursively translate result type, parameters and thrown list.
 2563               tree.restype = translate(tree.restype);
 2564               tree.params = translateVarDefs(tree.params);
 2565               tree.thrown = translate(tree.thrown);
 2566   
 2567               // when compiling stubs, don't process body
 2568               if (tree.body == null) {
 2569                   result = tree;
 2570                   return;
 2571               }
 2572   
 2573               // Add this$n (if needed) in front of and free variables behind
 2574               // constructor parameter list.
 2575               tree.params = tree.params.appendList(fvdefs);
 2576               if (currentClass.hasOuterInstance())
 2577                   tree.params = tree.params.prepend(otdef);
 2578   
 2579               // If this is an initial constructor, i.e., it does not start with
 2580               // this(...), insert initializers for this$n and proxies
 2581               // before (pre-1.4, after) the call to superclass constructor.
 2582               JCStatement selfCall = translate(tree.body.stats.head);
 2583   
 2584               List<JCStatement> added = List.nil();
 2585               if (fvs.nonEmpty()) {
 2586                   List<Type> addedargtypes = List.nil();
 2587                   for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
 2588                       if (TreeInfo.isInitialConstructor(tree))
 2589                           added = added.prepend(
 2590                               initField(tree.body.pos, proxyName(l.head.name)));
 2591                       addedargtypes = addedargtypes.prepend(l.head.erasure(types));
 2592                   }
 2593                   Type olderasure = m.erasure(types);
 2594                   m.erasure_field = new MethodType(
 2595                       olderasure.getParameterTypes().appendList(addedargtypes),
 2596                       olderasure.getReturnType(),
 2597                       olderasure.getThrownTypes(),
 2598                       syms.methodClass);
 2599               }
 2600               if (currentClass.hasOuterInstance() &&
 2601                   TreeInfo.isInitialConstructor(tree))
 2602               {
 2603                   added = added.prepend(initOuterThis(tree.body.pos));
 2604               }
 2605   
 2606               // pop local variables from proxy stack
 2607               proxies = proxies.leave();
 2608   
 2609               // recursively translate following local statements and
 2610               // combine with this- or super-call
 2611               List<JCStatement> stats = translate(tree.body.stats.tail);
 2612               if (target.initializeFieldsBeforeSuper())
 2613                   tree.body.stats = stats.prepend(selfCall).prependList(added);
 2614               else
 2615                   tree.body.stats = stats.prependList(added).prepend(selfCall);
 2616   
 2617               outerThisStack = prevOuterThisStack;
 2618           } else {
 2619               super.visitMethodDef(tree);
 2620           }
 2621           result = tree;
 2622       }
 2623   
 2624       public void visitTypeCast(JCTypeCast tree) {
 2625           tree.clazz = translate(tree.clazz);
 2626           if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
 2627               tree.expr = translate(tree.expr, tree.type);
 2628           else
 2629               tree.expr = translate(tree.expr);
 2630           result = tree;
 2631       }
 2632   
 2633       public void visitNewClass(JCNewClass tree) {
 2634           ClassSymbol c = (ClassSymbol)tree.constructor.owner;
 2635   
 2636           // Box arguments, if necessary
 2637           boolean isEnum = (tree.constructor.owner.flags() & ENUM) != 0;
 2638           List<Type> argTypes = tree.constructor.type.getParameterTypes();
 2639           if (isEnum) argTypes = argTypes.prepend(syms.intType).prepend(syms.stringType);
 2640           tree.args = boxArgs(argTypes, tree.args, tree.varargsElement);
 2641           tree.varargsElement = null;
 2642   
 2643           // If created class is local, add free variables after
 2644           // explicit constructor arguments.
 2645           if ((c.owner.kind & (VAR | MTH)) != 0) {
 2646               tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
 2647           }
 2648   
 2649           // If an access constructor is used, append null as a last argument.
 2650           Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
 2651           if (constructor != tree.constructor) {
 2652               tree.args = tree.args.append(makeNull());
 2653               tree.constructor = constructor;
 2654           }
 2655   
 2656           // If created class has an outer instance, and new is qualified, pass
 2657           // qualifier as first argument. If new is not qualified, pass the
 2658           // correct outer instance as first argument.
 2659           if (c.hasOuterInstance()) {
 2660               JCExpression thisArg;
 2661               if (tree.encl != null) {
 2662                   thisArg = attr.makeNullCheck(translate(tree.encl));
 2663                   thisArg.type = tree.encl.type;
 2664               } else if ((c.owner.kind & (MTH | VAR)) != 0) {
 2665                   // local class
 2666                   thisArg = makeThis(tree.pos(), c.type.getEnclosingType().tsym);
 2667               } else {
 2668                   // nested class
 2669                   thisArg = makeOwnerThis(tree.pos(), c, false);
 2670               }
 2671               tree.args = tree.args.prepend(thisArg);
 2672           }
 2673           tree.encl = null;
 2674   
 2675           // If we have an anonymous class, create its flat version, rather
 2676           // than the class or interface following new.
 2677           if (tree.def != null) {
 2678               translate(tree.def);
 2679               tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
 2680               tree.def = null;
 2681           } else {
 2682               tree.clazz = access(c, tree.clazz, enclOp, false);
 2683           }
 2684           result = tree;
 2685       }
 2686   
 2687       // Simplify conditionals with known constant controlling expressions.
 2688       // This allows us to avoid generating supporting declarations for
 2689       // the dead code, which will not be eliminated during code generation.
 2690       // Note that Flow.isFalse and Flow.isTrue only return true
 2691       // for constant expressions in the sense of JLS 15.27, which
 2692       // are guaranteed to have no side-effects.  More aggressive
 2693       // constant propagation would require that we take care to
 2694       // preserve possible side-effects in the condition expression.
 2695   
 2696       /** Visitor method for conditional expressions.
 2697        */
 2698       public void visitConditional(JCConditional tree) {
 2699           JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
 2700           if (cond.type.isTrue()) {
 2701               result = convert(translate(tree.truepart, tree.type), tree.type);
 2702           } else if (cond.type.isFalse()) {
 2703               result = convert(translate(tree.falsepart, tree.type), tree.type);
 2704           } else {
 2705               // Condition is not a compile-time constant.
 2706               tree.truepart = translate(tree.truepart, tree.type);
 2707               tree.falsepart = translate(tree.falsepart, tree.type);
 2708               result = tree;
 2709           }
 2710       }
 2711   //where
 2712           private JCTree convert(JCTree tree, Type pt) {
 2713               if (tree.type == pt || tree.type.tag == TypeTags.BOT)
 2714                   return tree;
 2715               JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree);
 2716               result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt)
 2717                                                              : pt;
 2718               return result;
 2719           }
 2720   
 2721       /** Visitor method for if statements.
 2722        */
 2723       public void visitIf(JCIf tree) {
 2724           JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
 2725           if (cond.type.isTrue()) {
 2726               result = translate(tree.thenpart);
 2727           } else if (cond.type.isFalse()) {
 2728               if (tree.elsepart != null) {
 2729                   result = translate(tree.elsepart);
 2730               } else {
 2731                   result = make.Skip();
 2732               }
 2733           } else {
 2734               // Condition is not a compile-time constant.
 2735               tree.thenpart = translate(tree.thenpart);
 2736               tree.elsepart = translate(tree.elsepart);
 2737               result = tree;
 2738           }
 2739       }
 2740   
 2741       /** Visitor method for assert statements. Translate them away.
 2742        */
 2743       public void visitAssert(JCAssert tree) {
 2744           DiagnosticPosition detailPos = (tree.detail == null) ? tree.pos() : tree.detail.pos();
 2745           tree.cond = translate(tree.cond, syms.booleanType);
 2746           if (!tree.cond.type.isTrue()) {
 2747               JCExpression cond = assertFlagTest(tree.pos());
 2748               List<JCExpression> exnArgs = (tree.detail == null) ?
 2749                   List.<JCExpression>nil() : List.of(translate(tree.detail));
 2750               if (!tree.cond.type.isFalse()) {
 2751                   cond = makeBinary
 2752                       (JCTree.AND,
 2753                        cond,
 2754                        makeUnary(JCTree.NOT, tree.cond));
 2755               }
 2756               result =
 2757                   make.If(cond,
 2758                           make_at(detailPos).
 2759                              Throw(makeNewClass(syms.assertionErrorType, exnArgs)),
 2760                           null);
 2761           } else {
 2762               result = make.Skip();
 2763           }
 2764       }
 2765   
 2766       public void visitApply(JCMethodInvocation tree) {
 2767           Symbol meth = TreeInfo.symbol(tree.meth);
 2768           List<Type> argtypes = meth.type.getParameterTypes();
 2769           if (allowEnums &&
 2770               meth.name==names.init &&
 2771               meth.owner == syms.enumSym)
 2772               argtypes = argtypes.tail.tail;
 2773           tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
 2774           tree.varargsElement = null;
 2775           Name methName = TreeInfo.name(tree.meth);
 2776           if (meth.name==names.init) {
 2777               // We are seeing a this(...) or super(...) constructor call.
 2778               // If an access constructor is used, append null as a last argument.
 2779               Symbol constructor = accessConstructor(tree.pos(), meth);
 2780               if (constructor != meth) {
 2781                   tree.args = tree.args.append(makeNull());
 2782                   TreeInfo.setSymbol(tree.meth, constructor);
 2783               }
 2784   
 2785               // If we are calling a constructor of a local class, add
 2786               // free variables after explicit constructor arguments.
 2787               ClassSymbol c = (ClassSymbol)constructor.owner;
 2788               if ((c.owner.kind & (VAR | MTH)) != 0) {
 2789                   tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
 2790               }
 2791   
 2792               // If we are calling a constructor of an enum class, pass
 2793               // along the name and ordinal arguments
 2794               if ((c.flags_field&ENUM) != 0 || c.getQualifiedName() == names.java_lang_Enum) {
 2795                   List<JCVariableDecl> params = currentMethodDef.params;
 2796                   if (currentMethodSym.owner.hasOuterInstance())
 2797                       params = params.tail; // drop this$n
 2798                   tree.args = tree.args
 2799                       .prepend(make_at(tree.pos()).Ident(params.tail.head.sym)) // ordinal
 2800                       .prepend(make.Ident(params.head.sym)); // name
 2801               }
 2802   
 2803               // If we are calling a constructor of a class with an outer
 2804               // instance, and the call
 2805               // is qualified, pass qualifier as first argument in front of
 2806               // the explicit constructor arguments. If the call
 2807               // is not qualified, pass the correct outer instance as
 2808               // first argument.
 2809               if (c.hasOuterInstance()) {
 2810                   JCExpression thisArg;
 2811                   if (tree.meth.getTag() == JCTree.SELECT) {
 2812                       thisArg = attr.
 2813                           makeNullCheck(translate(((JCFieldAccess) tree.meth).selected));
 2814                       tree.meth = make.Ident(constructor);
 2815                       ((JCIdent) tree.meth).name = methName;
 2816                   } else if ((c.owner.kind & (MTH | VAR)) != 0 || methName == names._this){
 2817                       // local class or this() call
 2818                       thisArg = makeThis(tree.meth.pos(), c.type.getEnclosingType().tsym);
 2819                   } else {
 2820                       // super() call of nested class - never pick 'this'
 2821                       thisArg = makeOwnerThisN(tree.meth.pos(), c, false);
 2822                   }
 2823                   tree.args = tree.args.prepend(thisArg);
 2824               }
 2825           } else {
 2826               // We are seeing a normal method invocation; translate this as usual.
 2827               tree.meth = translate(tree.meth);
 2828   
 2829               // If the translated method itself is an Apply tree, we are
 2830               // seeing an access method invocation. In this case, append
 2831               // the method arguments to the arguments of the access method.
 2832               if (tree.meth.getTag() == JCTree.APPLY) {
 2833                   JCMethodInvocation app = (JCMethodInvocation)tree.meth;
 2834                   app.args = tree.args.prependList(app.args);
 2835                   result = app;
 2836                   return;
 2837               }
 2838           }
 2839           result = tree;
 2840       }
 2841   
 2842       List<JCExpression> boxArgs(List<Type> parameters, List<JCExpression> _args, Type varargsElement) {
 2843           List<JCExpression> args = _args;
 2844           if (parameters.isEmpty()) return args;
 2845           boolean anyChanges = false;
 2846           ListBuffer<JCExpression> result = new ListBuffer<JCExpression>();
 2847           while (parameters.tail.nonEmpty()) {
 2848               JCExpression arg = translate(args.head, parameters.head);
 2849               anyChanges |= (arg != args.head);
 2850               result.append(arg);
 2851               args = args.tail;
 2852               parameters = parameters.tail;
 2853           }
 2854           Type parameter = parameters.head;
 2855           if (varargsElement != null) {
 2856               anyChanges = true;
 2857               ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
 2858               while (args.nonEmpty()) {
 2859                   JCExpression arg = translate(args.head, varargsElement);
 2860                   elems.append(arg);
 2861                   args = args.tail;
 2862               }
 2863               JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
 2864                                                  List.<JCExpression>nil(),
 2865                                                  elems.toList());
 2866               boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
 2867               result.append(boxedArgs);
 2868           } else {
 2869               if (args.length() != 1) throw new AssertionError(args);
 2870               JCExpression arg = translate(args.head, parameter);
 2871               anyChanges |= (arg != args.head);
 2872               result.append(arg);
 2873               if (!anyChanges) return _args;
 2874           }
 2875           return result.toList();
 2876       }
 2877   
 2878       /** Expand a boxing or unboxing conversion if needed. */
 2879       @SuppressWarnings("unchecked") // XXX unchecked
 2880       <T extends JCTree> T boxIfNeeded(T tree, Type type) {
 2881           boolean havePrimitive = tree.type.isPrimitive();
 2882           if (havePrimitive == type.isPrimitive())
 2883               return tree;
 2884           if (havePrimitive) {
 2885               Type unboxedTarget = types.unboxedType(type);
 2886               if (unboxedTarget.tag != NONE) {
 2887                   if (!types.isSubtype(tree.type, unboxedTarget)) //e.g. Character c = 89;
 2888                       tree.type = unboxedTarget.constType(tree.type.constValue());
 2889                   return (T)boxPrimitive((JCExpression)tree, type);
 2890               } else {
 2891                   tree = (T)boxPrimitive((JCExpression)tree);
 2892               }
 2893           } else {
 2894               tree = (T)unbox((JCExpression)tree, type);
 2895           }
 2896           return tree;
 2897       }
 2898   
 2899       /** Box up a single primitive expression. */
 2900       JCExpression boxPrimitive(JCExpression tree) {
 2901           return boxPrimitive(tree, types.boxedClass(tree.type).type);
 2902       }
 2903   
 2904       /** Box up a single primitive expression. */
 2905       JCExpression boxPrimitive(JCExpression tree, Type box) {
 2906           make_at(tree.pos());
 2907           if (target.boxWithConstructors()) {
 2908               Symbol ctor = lookupConstructor(tree.pos(),
 2909                                               box,
 2910                                               List.<Type>nil()
 2911                                               .prepend(tree.type));
 2912               return make.Create(ctor, List.of(tree));
 2913           } else {
 2914               Symbol valueOfSym = lookupMethod(tree.pos(),
 2915                                                names.valueOf,
 2916                                                box,
 2917                                                List.<Type>nil()
 2918                                                .prepend(tree.type));
 2919               return make.App(make.QualIdent(valueOfSym), List.of(tree));
 2920           }
 2921       }
 2922   
 2923       /** Unbox an object to a primitive value. */
 2924       JCExpression unbox(JCExpression tree, Type primitive) {
 2925           Type unboxedType = types.unboxedType(tree.type);
 2926           if (unboxedType.tag == NONE) {
 2927               unboxedType = primitive;
 2928               if (!unboxedType.isPrimitive())
 2929                   throw new AssertionError(unboxedType);
 2930               make_at(tree.pos());
 2931               tree = make.TypeCast(types.boxedClass(unboxedType).type, tree);
 2932           } else {
 2933               // There must be a conversion from unboxedType to primitive.
 2934               if (!types.isSubtype(unboxedType, primitive))
 2935                   throw new AssertionError(tree);
 2936           }
 2937           make_at(tree.pos());
 2938           Symbol valueSym = lookupMethod(tree.pos(),
 2939                                          unboxedType.tsym.name.append(names.Value), // x.intValue()
 2940                                          tree.type,
 2941                                          List.<Type>nil());
 2942           return make.App(make.Select(tree, valueSym));
 2943       }
 2944   
 2945       /** Visitor method for parenthesized expressions.
 2946        *  If the subexpression has changed, omit the parens.
 2947        */
 2948       public void visitParens(JCParens tree) {
 2949           JCTree expr = translate(tree.expr);
 2950           result = ((expr == tree.expr) ? tree : expr);
 2951       }
 2952   
 2953       public void visitIndexed(JCArrayAccess tree) {
 2954           tree.indexed = translate(tree.indexed);
 2955           tree.index = translate(tree.index, syms.intType);
 2956           result = tree;
 2957       }
 2958   
 2959       public void visitAssign(JCAssign tree) {
 2960           tree.lhs = translate(tree.lhs, tree);
 2961           tree.rhs = translate(tree.rhs, tree.lhs.type);
 2962   
 2963           // If translated left hand side is an Apply, we are
 2964           // seeing an access method invocation. In this case, append
 2965           // right hand side as last argument of the access method.
 2966           if (tree.lhs.getTag() == JCTree.APPLY) {
 2967               JCMethodInvocation app = (JCMethodInvocation)tree.lhs;
 2968               app.args = List.of(tree.rhs).prependList(app.args);
 2969               result = app;
 2970           } else {
 2971               result = tree;
 2972           }
 2973       }
 2974   
 2975       public void visitAssignop(final JCAssignOp tree) {
 2976           if (!tree.lhs.type.isPrimitive() &&
 2977               tree.operator.type.getReturnType().isPrimitive()) {
 2978               // boxing required; need to rewrite as x = (unbox typeof x)(x op y);
 2979               // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y)
 2980               // (but without recomputing x)
 2981               JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() {
 2982                       public JCTree build(final JCTree lhs) {
 2983                           int newTag = tree.getTag() - JCTree.ASGOffset;
 2984                           // Erasure (TransTypes) can change the type of
 2985                           // tree.lhs.  However, we can still get the
 2986                           // unerased type of tree.lhs as it is stored
 2987                           // in tree.type in Attr.
 2988                           Symbol newOperator = rs.resolveBinaryOperator(tree.pos(),
 2989                                                                         newTag,
 2990                                                                         attrEnv,
 2991                                                                         tree.type,
 2992                                                                         tree.rhs.type);
 2993                           JCExpression expr = (JCExpression)lhs;
 2994                           if (expr.type != tree.type)
 2995                               expr = make.TypeCast(tree.type, expr);
 2996                           JCBinary opResult = make.Binary(newTag, expr, tree.rhs);
 2997                           opResult.operator = newOperator;
 2998                           opResult.type = newOperator.type.getReturnType();
 2999                           JCTypeCast newRhs = make.TypeCast(types.unboxedType(tree.type),
 3000                                                             opResult);
 3001                           return make.Assign((JCExpression)lhs, newRhs).setType(tree.type);
 3002                       }
 3003                   });
 3004               result = translate(newTree);
 3005               return;
 3006           }
 3007           tree.lhs = translate(tree.lhs, tree);
 3008           tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
 3009   
 3010           // If translated left hand side is an Apply, we are
 3011           // seeing an access method invocation. In this case, append
 3012           // right hand side as last argument of the access method.
 3013           if (tree.lhs.getTag() == JCTree.APPLY) {
 3014               JCMethodInvocation app = (JCMethodInvocation)tree.lhs;
 3015               // if operation is a += on strings,
 3016               // make sure to convert argument to string
 3017               JCExpression rhs = (((OperatorSymbol)tree.operator).opcode == string_add)
 3018                 ? makeString(tree.rhs)
 3019                 : tree.rhs;
 3020               app.args = List.of(rhs).prependList(app.args);
 3021               result = app;
 3022           } else {
 3023               result = tree;
 3024           }
 3025       }
 3026   
 3027       /** Lower a tree of the form e++ or e-- where e is an object type */
 3028       JCTree lowerBoxedPostop(final JCUnary tree) {
 3029           // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2
 3030           // or
 3031           // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2
 3032           // where OP is += or -=
 3033           final boolean cast = TreeInfo.skipParens(tree.arg).getTag() == JCTree.TYPECAST;
 3034           return abstractLval(tree.arg, new TreeBuilder() {
 3035                   public JCTree build(final JCTree tmp1) {
 3036                       return abstractRval(tmp1, tree.arg.type, new TreeBuilder() {
 3037                               public JCTree build(final JCTree tmp2) {
 3038                                   int opcode = (tree.getTag() == JCTree.POSTINC)
 3039                                       ? JCTree.PLUS_ASG : JCTree.MINUS_ASG;
 3040                                   JCTree lhs = cast
 3041                                       ? make.TypeCast(tree.arg.type, (JCExpression)tmp1)
 3042                                       : tmp1;
 3043                                   JCTree update = makeAssignop(opcode,
 3044                                                                lhs,
 3045                                                                make.Literal(1));
 3046                                   return makeComma(update, tmp2);
 3047                               }
 3048                           });
 3049                   }
 3050               });
 3051       }
 3052   
 3053       public void visitUnary(JCUnary tree) {
 3054           boolean isUpdateOperator =
 3055               JCTree.PREINC <= tree.getTag() && tree.getTag() <= JCTree.POSTDEC;
 3056           if (isUpdateOperator && !tree.arg.type.isPrimitive()) {
 3057               switch(tree.getTag()) {
 3058               case JCTree.PREINC:            // ++ e
 3059                       // translate to e += 1
 3060               case JCTree.PREDEC:            // -- e
 3061                       // translate to e -= 1
 3062                   {
 3063                       int opcode = (tree.getTag() == JCTree.PREINC)
 3064                           ? JCTree.PLUS_ASG : JCTree.MINUS_ASG;
 3065                       JCAssignOp newTree = makeAssignop(opcode,
 3066                                                       tree.arg,
 3067                                                       make.Literal(1));
 3068                       result = translate(newTree, tree.type);
 3069                       return;
 3070                   }
 3071               case JCTree.POSTINC:           // e ++
 3072               case JCTree.POSTDEC:           // e --
 3073                   {
 3074                       result = translate(lowerBoxedPostop(tree), tree.type);
 3075                       return;
 3076                   }
 3077               }
 3078               throw new AssertionError(tree);
 3079           }
 3080   
 3081           tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
 3082   
 3083           if (tree.getTag() == JCTree.NOT && tree.arg.type.constValue() != null) {
 3084               tree.type = cfolder.fold1(bool_not, tree.arg.type);
 3085           }
 3086   
 3087           // If translated left hand side is an Apply, we are
 3088           // seeing an access method invocation. In this case, return
 3089           // that access method invocation as result.
 3090           if (isUpdateOperator && tree.arg.getTag() == JCTree.APPLY) {
 3091               result = tree.arg;
 3092           } else {
 3093               result = tree;
 3094           }
 3095       }
 3096   
 3097       public void visitBinary(JCBinary tree) {
 3098           List<Type> formals = tree.operator.type.getParameterTypes();
 3099           JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
 3100           switch (tree.getTag()) {
 3101           case JCTree.OR:
 3102               if (lhs.type.isTrue()) {
 3103                   result = lhs;
 3104                   return;
 3105               }
 3106               if (lhs.type.isFalse()) {
 3107                   result = translate(tree.rhs, formals.tail.head);
 3108                   return;
 3109               }
 3110               break;
 3111           case JCTree.AND:
 3112               if (lhs.type.isFalse()) {
 3113                   result = lhs;
 3114                   return;
 3115               }
 3116               if (lhs.type.isTrue()) {
 3117                   result = translate(tree.rhs, formals.tail.head);
 3118                   return;
 3119               }
 3120               break;
 3121           }
 3122           tree.rhs = translate(tree.rhs, formals.tail.head);
 3123           result = tree;
 3124       }
 3125   
 3126       public void visitIdent(JCIdent tree) {
 3127           result = access(tree.sym, tree, enclOp, false);
 3128       }
 3129   
 3130       /** Translate away the foreach loop.  */
 3131       public void visitForeachLoop(JCEnhancedForLoop tree) {
 3132           if (types.elemtype(tree.expr.type) == null)
 3133               visitIterableForeachLoop(tree);
 3134           else
 3135               visitArrayForeachLoop(tree);
 3136       }
 3137           // where
 3138           /**
 3139            * A statement of the form
 3140            *
 3141            * <pre>
 3142            *     for ( T v : arrayexpr ) stmt;
 3143            * </pre>
 3144            *
 3145            * (where arrayexpr is of an array type) gets translated to
 3146            *
 3147            * <pre>
 3148            *     for ( { arraytype #arr = arrayexpr;
 3149            *             int #len = array.length;
 3150            *             int #i = 0; };
 3151            *           #i < #len; i$++ ) {
 3152            *         T v = arr$[#i];
 3153            *         stmt;
 3154            *     }
 3155            * </pre>
 3156            *
 3157            * where #arr, #len, and #i are freshly named synthetic local variables.
 3158            */
 3159           private void visitArrayForeachLoop(JCEnhancedForLoop tree) {
 3160               make_at(tree.expr.pos());
 3161               VarSymbol arraycache = new VarSymbol(0,
 3162                                                    names.fromString("arr" + target.syntheticNameChar()),
 3163                                                    tree.expr.type,
 3164                                                    currentMethodSym);
 3165               JCStatement arraycachedef = make.VarDef(arraycache, tree.expr);
 3166               VarSymbol lencache = new VarSymbol(0,
 3167                                                  names.fromString("len" + target.syntheticNameChar()),
 3168                                                  syms.intType,
 3169                                                  currentMethodSym);
 3170               JCStatement lencachedef = make.
 3171                   VarDef(lencache, make.Select(make.Ident(arraycache), syms.lengthVar));
 3172               VarSymbol index = new VarSymbol(0,
 3173                                               names.fromString("i" + target.syntheticNameChar()),
 3174                                               syms.intType,
 3175                                               currentMethodSym);
 3176   
 3177               JCVariableDecl indexdef = make.VarDef(index, make.Literal(INT, 0));
 3178               indexdef.init.type = indexdef.type = syms.intType.constType(0);
 3179   
 3180               List<JCStatement> loopinit = List.of(arraycachedef, lencachedef, indexdef);
 3181               JCBinary cond = makeBinary(JCTree.LT, make.Ident(index), make.Ident(lencache));
 3182   
 3183               JCExpressionStatement step = make.Exec(makeUnary(JCTree.PREINC, make.Ident(index)));
 3184   
 3185               Type elemtype = types.elemtype(tree.expr.type);
 3186               JCExpression loopvarinit = make.Indexed(make.Ident(arraycache),
 3187                                                       make.Ident(index)).setType(elemtype);
 3188               JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods,
 3189                                                     tree.var.name,
 3190                                                     tree.var.vartype,
 3191                                                     loopvarinit).setType(tree.var.type);
 3192               loopvardef.sym = tree.var.sym;
 3193               JCBlock body = make.
 3194                   Block(0, List.of(loopvardef, tree.body));
 3195   
 3196               result = translate(make.
 3197                                  ForLoop(loopinit,
 3198                                          cond,
 3199                                          List.of(step),
 3200                                          body));
 3201               patchTargets(body, tree, result);
 3202           }
 3203           /** Patch up break and continue targets. */
 3204           private void patchTargets(JCTree body, final JCTree src, final JCTree dest) {
 3205               class Patcher extends TreeScanner {
 3206                   public void visitBreak(JCBreak tree) {
 3207                       if (tree.target == src)
 3208                           tree.target = dest;
 3209                   }
 3210                   public void visitContinue(JCContinue tree) {
 3211                       if (tree.target == src)
 3212                           tree.target = dest;
 3213                   }
 3214                   public void visitClassDef(JCClassDecl tree) {}
 3215               }
 3216               new Patcher().scan(body);
 3217           }
 3218           /**
 3219            * A statement of the form
 3220            *
 3221            * <pre>
 3222            *     for ( T v : coll ) stmt ;
 3223            * </pre>
 3224            *
 3225            * (where coll implements Iterable<? extends T>) gets translated to
 3226            *
 3227            * <pre>
 3228            *     for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
 3229            *         T v = (T) #i.next();
 3230            *         stmt;
 3231            *     }
 3232            * </pre>
 3233            *
 3234            * where #i is a freshly named synthetic local variable.
 3235            */
 3236           private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
 3237               make_at(tree.expr.pos());
 3238               Type iteratorTarget = syms.objectType;
 3239               Type iterableType = types.asSuper(types.upperBound(tree.expr.type),
 3240                                                 syms.iterableType.tsym);
 3241               if (iterableType.getTypeArguments().nonEmpty())
 3242                   iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
 3243               Type eType = tree.expr.type;
 3244               tree.expr.type = types.erasure(eType);
 3245               if (eType.tag == TYPEVAR && eType.getUpperBound().isCompound())
 3246                   tree.expr = make.TypeCast(types.erasure(iterableType), tree.expr);
 3247               Symbol iterator = lookupMethod(tree.expr.pos(),
 3248                                              names.iterator,
 3249                                              types.erasure(syms.iterableType),
 3250                                              List.<Type>nil());
 3251               VarSymbol itvar = new VarSymbol(0, names.fromString("i" + target.syntheticNameChar()),
 3252                                               types.erasure(iterator.type.getReturnType()),
 3253                                               currentMethodSym);
 3254               JCStatement init = make.
 3255                   VarDef(itvar,
 3256                          make.App(make.Select(tree.expr, iterator)));
 3257               Symbol hasNext = lookupMethod(tree.expr.pos(),
 3258                                             names.hasNext,
 3259                                             itvar.type,
 3260                                             List.<Type>nil());
 3261               JCMethodInvocation cond = make.App(make.Select(make.Ident(itvar), hasNext));
 3262               Symbol next = lookupMethod(tree.expr.pos(),
 3263                                          names.next,
 3264                                          itvar.type,
 3265                                          List.<Type>nil());
 3266               JCExpression vardefinit = make.App(make.Select(make.Ident(itvar), next));
 3267               if (tree.var.type.isPrimitive())
 3268                   vardefinit = make.TypeCast(types.upperBound(iteratorTarget), vardefinit);
 3269               else
 3270                   vardefinit = make.TypeCast(tree.var.type, vardefinit);
 3271               JCVariableDecl indexDef = (JCVariableDecl)make.VarDef(tree.var.mods,
 3272                                                     tree.var.name,
 3273                                                     tree.var.vartype,
 3274                                                     vardefinit).setType(tree.var.type);
 3275               indexDef.sym = tree.var.sym;
 3276               JCBlock body = make.Block(0, List.of(indexDef, tree.body));
 3277               body.endpos = TreeInfo.endPos(tree.body);
 3278               result = translate(make.
 3279                   ForLoop(List.of(init),
 3280                           cond,
 3281                           List.<JCExpressionStatement>nil(),
 3282                           body));
 3283               patchTargets(body, tree, result);
 3284           }
 3285   
 3286       public void visitVarDef(JCVariableDecl tree) {
 3287           MethodSymbol oldMethodSym = currentMethodSym;
 3288           tree.mods = translate(tree.mods);
 3289           tree.vartype = translate(tree.vartype);
 3290           if (currentMethodSym == null) {
 3291               // A class or instance field initializer.
 3292               currentMethodSym =
 3293                   new MethodSymbol((tree.mods.flags&STATIC) | BLOCK,
 3294                                    names.empty, null,
 3295                                    currentClass);
 3296           }
 3297           if (tree.init != null) tree.init = translate(tree.init, tree.type);
 3298           result = tree;
 3299           currentMethodSym = oldMethodSym;
 3300       }
 3301   
 3302       public void visitBlock(JCBlock tree) {
 3303           MethodSymbol oldMethodSym = currentMethodSym;
 3304           if (currentMethodSym == null) {
 3305               // Block is a static or instance initializer.
 3306               currentMethodSym =
 3307                   new MethodSymbol(tree.flags | BLOCK,
 3308                                    names.empty, null,
 3309                                    currentClass);
 3310           }
 3311           super.visitBlock(tree);
 3312           currentMethodSym = oldMethodSym;
 3313       }
 3314   
 3315       public void visitDoLoop(JCDoWhileLoop tree) {
 3316           tree.body = translate(tree.body);
 3317           tree.cond = translate(tree.cond, syms.booleanType);
 3318           result = tree;
 3319       }
 3320   
 3321       public void visitWhileLoop(JCWhileLoop tree) {
 3322           tree.cond = translate(tree.cond, syms.booleanType);
 3323           tree.body = translate(tree.body);
 3324           result = tree;
 3325       }
 3326   
 3327       public void visitForLoop(JCForLoop tree) {
 3328           tree.init = translate(tree.init);
 3329           if (tree.cond != null)
 3330               tree.cond = translate(tree.cond, syms.booleanType);
 3331           tree.step = translate(tree.step);
 3332           tree.body = translate(tree.body);
 3333           result = tree;
 3334       }
 3335   
 3336       public void visitReturn(JCReturn tree) {
 3337           if (tree.expr != null)
 3338               tree.expr = translate(tree.expr,
 3339                                     types.erasure(currentMethodDef
 3340                                                   .restype.type));
 3341           result = tree;
 3342       }
 3343   
 3344       public void visitSwitch(JCSwitch tree) {
 3345           Type selsuper = types.supertype(tree.selector.type);
 3346           boolean enumSwitch = selsuper != null &&
 3347               (tree.selector.type.tsym.flags() & ENUM) != 0;
 3348           boolean stringSwitch = selsuper != null &&
 3349               types.isSameType(tree.selector.type, syms.stringType);
 3350           Type target = enumSwitch ? tree.selector.type :
 3351               (stringSwitch? syms.stringType : syms.intType);
 3352           tree.selector = translate(tree.selector, target);
 3353           tree.cases = translateCases(tree.cases);
 3354           if (enumSwitch) {
 3355               result = visitEnumSwitch(tree);
 3356           } else if (stringSwitch) {
 3357               result = visitStringSwitch(tree);
 3358           } else {
 3359               result = tree;
 3360           }
 3361       }
 3362   
 3363       public JCTree visitEnumSwitch(JCSwitch tree) {
 3364           TypeSymbol enumSym = tree.selector.type.tsym;
 3365           EnumMapping map = mapForEnum(tree.pos(), enumSym);
 3366           make_at(tree.pos());
 3367           Symbol ordinalMethod = lookupMethod(tree.pos(),
 3368                                               names.ordinal,
 3369                                               tree.selector.type,
 3370                                               List.<Type>nil());
 3371           JCArrayAccess selector = make.Indexed(map.mapVar,
 3372                                           make.App(make.Select(tree.selector,
 3373                                                                ordinalMethod)));
 3374           ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
 3375           for (JCCase c : tree.cases) {
 3376               if (c.pat != null) {
 3377                   VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pat);
 3378                   JCLiteral pat = map.forConstant(label);
 3379                   cases.append(make.Case(pat, c.stats));
 3380               } else {
 3381                   cases.append(c);
 3382               }
 3383           }
 3384           JCSwitch enumSwitch = make.Switch(selector, cases.toList());
 3385           patchTargets(enumSwitch, tree, enumSwitch);
 3386           return enumSwitch;
 3387       }
 3388   
 3389       public JCTree visitStringSwitch(JCSwitch tree) {
 3390           List<JCCase> caseList = tree.getCases();
 3391           int alternatives = caseList.size();
 3392   
 3393           if (alternatives == 0) { // Strange but legal possibility
 3394               return make.at(tree.pos()).Exec(attr.makeNullCheck(tree.getExpression()));
 3395           } else {
 3396               /*
 3397                * The general approach used is to translate a single
 3398                * string switch statement into a series of two chained
 3399                * switch statements: the first a synthesized statement
 3400                * switching on the argument string's hash value and
 3401                * computing a string's position in the list of original
 3402                * case labels, if any, followed by a second switch on the
 3403                * computed integer value.  The second switch has the same
 3404                * code structure as the original string switch statement
 3405                * except that the string case labels are replaced with
 3406                * positional integer constants starting at 0.
 3407                *
 3408                * The first switch statement can be thought of as an
 3409                * inlined map from strings to their position in the case
 3410                * label list.  An alternate implementation would use an
 3411                * actual Map for this purpose, as done for enum switches.
 3412                *
 3413                * With some additional effort, it would be possible to
 3414                * use a single switch statement on the hash code of the
 3415                * argument, but care would need to be taken to preserve
 3416                * the proper control flow in the presence of hash
 3417                * collisions and other complications, such as
 3418                * fallthroughs.  Switch statements with one or two
 3419                * alternatives could also be specially translated into
 3420                * if-then statements to omit the computation of the hash
 3421                * code.
 3422                *
 3423                * The generated code assumes that the hashing algorithm
 3424                * of String is the same in the compilation environment as
 3425                * in the environment the code will run in.  The string
 3426                * hashing algorithm in the SE JDK has been unchanged
 3427                * since at least JDK 1.2.  Since the algorithm has been
 3428                * specified since that release as well, it is very
 3429                * unlikely to be changed in the future.
 3430                *
 3431                * Different hashing algorithms, such as the length of the
 3432                * strings or a perfect hashing algorithm over the
 3433                * particular set of case labels, could potentially be
 3434                * used instead of String.hashCode.
 3435                */
 3436   
 3437               ListBuffer<JCStatement> stmtList = new ListBuffer<JCStatement>();
 3438   
 3439               // Map from String case labels to their original position in
 3440               // the list of case labels.
 3441               Map<String, Integer> caseLabelToPosition =
 3442                   new LinkedHashMap<String, Integer>(alternatives + 1, 1.0f);
 3443   
 3444               // Map of hash codes to the string case labels having that hashCode.
 3445               Map<Integer, Set<String>> hashToString =
 3446                   new LinkedHashMap<Integer, Set<String>>(alternatives + 1, 1.0f);
 3447   
 3448               int casePosition = 0;
 3449               for(JCCase oneCase : caseList) {
 3450                   JCExpression expression = oneCase.getExpression();
 3451   
 3452                   if (expression != null) { // expression for a "default" case is null
 3453                       String labelExpr = (String) expression.type.constValue();
 3454                       Integer mapping = caseLabelToPosition.put(labelExpr, casePosition);
 3455                       Assert.checkNull(mapping);
 3456                       int hashCode = labelExpr.hashCode();
 3457   
 3458                       Set<String> stringSet = hashToString.get(hashCode);
 3459                       if (stringSet == null) {
 3460                           stringSet = new LinkedHashSet<String>(1, 1.0f);
 3461                           stringSet.add(labelExpr);
 3462                           hashToString.put(hashCode, stringSet);
 3463                       } else {
 3464                           boolean added = stringSet.add(labelExpr);
 3465                           Assert.check(added);
 3466                       }
 3467                   }
 3468                   casePosition++;
 3469               }
 3470   
 3471               // Synthesize a switch statement that has the effect of
 3472               // mapping from a string to the integer position of that
 3473               // string in the list of case labels.  This is done by
 3474               // switching on the hashCode of the string followed by an
 3475               // if-then-else chain comparing the input for equality
 3476               // with all the case labels having that hash value.
 3477   
 3478               /*
 3479                * s$ = top of stack;
 3480                * tmp$ = -1;
 3481                * switch($s.hashCode()) {
 3482                *     case caseLabel.hashCode:
 3483                *         if (s$.equals("caseLabel_1")
 3484                *           tmp$ = caseLabelToPosition("caseLabel_1");
 3485                *         else if (s$.equals("caseLabel_2"))
 3486                *           tmp$ = caseLabelToPosition("caseLabel_2");
 3487                *         ...
 3488                *         break;
 3489                * ...
 3490                * }
 3491                */
 3492   
 3493               VarSymbol dollar_s = new VarSymbol(FINAL|SYNTHETIC,
 3494                                                  names.fromString("s" + tree.pos + target.syntheticNameChar()),
 3495                                                  syms.stringType,
 3496                                                  currentMethodSym);
 3497               stmtList.append(make.at(tree.pos()).VarDef(dollar_s, tree.getExpression()).setType(dollar_s.type));
 3498   
 3499               VarSymbol dollar_tmp = new VarSymbol(SYNTHETIC,
 3500                                                    names.fromString("tmp" + tree.pos + target.syntheticNameChar()),
 3501                                                    syms.intType,
 3502                                                    currentMethodSym);
 3503               JCVariableDecl dollar_tmp_def =
 3504                   (JCVariableDecl)make.VarDef(dollar_tmp, make.Literal(INT, -1)).setType(dollar_tmp.type);
 3505               dollar_tmp_def.init.type = dollar_tmp.type = syms.intType;
 3506               stmtList.append(dollar_tmp_def);
 3507               ListBuffer<JCCase> caseBuffer = ListBuffer.lb();
 3508               // hashCode will trigger nullcheck on original switch expression
 3509               JCMethodInvocation hashCodeCall = makeCall(make.Ident(dollar_s),
 3510                                                          names.hashCode,
 3511                                                          List.<JCExpression>nil()).setType(syms.intType);
 3512               JCSwitch switch1 = make.Switch(hashCodeCall,
 3513                                           caseBuffer.toList());
 3514               for(Map.Entry<Integer, Set<String>> entry : hashToString.entrySet()) {
 3515                   int hashCode = entry.getKey();
 3516                   Set<String> stringsWithHashCode = entry.getValue();
 3517                   Assert.check(stringsWithHashCode.size() >= 1);
 3518   
 3519                   JCStatement elsepart = null;
 3520                   for(String caseLabel : stringsWithHashCode ) {
 3521                       JCMethodInvocation stringEqualsCall = makeCall(make.Ident(dollar_s),
 3522                                                                      names.equals,
 3523                                                                      List.<JCExpression>of(make.Literal(caseLabel)));
 3524                       elsepart = make.If(stringEqualsCall,
 3525                                          make.Exec(make.Assign(make.Ident(dollar_tmp),
 3526                                                                make.Literal(caseLabelToPosition.get(caseLabel))).
 3527                                                    setType(dollar_tmp.type)),
 3528                                          elsepart);
 3529                   }
 3530   
 3531                   ListBuffer<JCStatement> lb = ListBuffer.lb();
 3532                   JCBreak breakStmt = make.Break(null);
 3533                   breakStmt.target = switch1;
 3534                   lb.append(elsepart).append(breakStmt);
 3535   
 3536                   caseBuffer.append(make.Case(make.Literal(hashCode), lb.toList()));
 3537               }
 3538   
 3539               switch1.cases = caseBuffer.toList();
 3540               stmtList.append(switch1);
 3541   
 3542               // Make isomorphic switch tree replacing string labels
 3543               // with corresponding integer ones from the label to
 3544               // position map.
 3545   
 3546               ListBuffer<JCCase> lb = ListBuffer.lb();
 3547               JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
 3548               for(JCCase oneCase : caseList ) {
 3549                   // Rewire up old unlabeled break statements to the
 3550                   // replacement switch being created.
 3551                   patchTargets(oneCase, tree, switch2);
 3552   
 3553                   boolean isDefault = (oneCase.getExpression() == null);
 3554                   JCExpression caseExpr;
 3555                   if (isDefault)
 3556                       caseExpr = null;
 3557                   else {
 3558                       caseExpr = make.Literal(caseLabelToPosition.get((String)oneCase.
 3559                                                                       getExpression().
 3560                                                                       type.constValue()));
 3561                   }
 3562   
 3563                   lb.append(make.Case(caseExpr,
 3564                                       oneCase.getStatements()));
 3565               }
 3566   
 3567               switch2.cases = lb.toList();
 3568               stmtList.append(switch2);
 3569   
 3570               return make.Block(0L, stmtList.toList());
 3571           }
 3572       }
 3573   
 3574       public void visitNewArray(JCNewArray tree) {
 3575           tree.elemtype = translate(tree.elemtype);
 3576           for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
 3577               if (t.head != null) t.head = translate(t.head, syms.intType);
 3578           tree.elems = translate(tree.elems, types.elemtype(tree.type));
 3579           result = tree;
 3580       }
 3581   
 3582       public void visitSelect(JCFieldAccess tree) {
 3583           // need to special case-access of the form C.super.x
 3584           // these will always need an access method.
 3585           boolean qualifiedSuperAccess =
 3586               tree.selected.getTag() == JCTree.SELECT &&
 3587               TreeInfo.name(tree.selected) == names._super;
 3588           tree.selected = translate(tree.selected);
 3589           if (tree.name == names._class)
 3590               result = classOf(tree.selected);
 3591           else if (tree.name == names._this || tree.name == names._super)
 3592               result = makeThis(tree.pos(), tree.selected.type.tsym);
 3593           else
 3594               result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
 3595       }
 3596   
 3597       public void visitLetExpr(LetExpr tree) {
 3598           tree.defs = translateVarDefs(tree.defs);
 3599           tree.expr = translate(tree.expr, tree.type);
 3600           result = tree;
 3601       }
 3602   
 3603       // There ought to be nothing to rewrite here;
 3604       // we don't generate code.
 3605       public void visitAnnotation(JCAnnotation tree) {
 3606           result = tree;
 3607       }
 3608   
 3609       @Override
 3610       public void visitTry(JCTry tree) {
 3611           if (tree.resources.isEmpty()) {
 3612               super.visitTry(tree);
 3613           } else {
 3614               result = makeTwrTry(tree);
 3615           }
 3616       }
 3617   
 3618   /**************************************************************************
 3619    * main method
 3620    *************************************************************************/
 3621   
 3622       /** Translate a toplevel class and return a list consisting of
 3623        *  the translated class and translated versions of all inner classes.
 3624        *  @param env   The attribution environment current at the class definition.
 3625        *               We need this for resolving some additional symbols.
 3626        *  @param cdef  The tree representing the class definition.
 3627        */
 3628       public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
 3629           ListBuffer<JCTree> translated = null;
 3630           try {
 3631               attrEnv = env;
 3632               this.make = make;
 3633               endPositions = env.toplevel.endPositions;
 3634               currentClass = null;
 3635               currentMethodDef = null;
 3636               outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null;
 3637               outermostMemberDef = null;
 3638               this.translated = new ListBuffer<JCTree>();
 3639               classdefs = new HashMap<ClassSymbol,JCClassDecl>();
 3640               actualSymbols = new HashMap<Symbol,Symbol>();
 3641               freevarCache = new HashMap<ClassSymbol,List<VarSymbol>>();
 3642               proxies = new Scope(syms.noSymbol);
 3643               twrVars = new Scope(syms.noSymbol);
 3644               outerThisStack = List.nil();
 3645               accessNums = new HashMap<Symbol,Integer>();
 3646               accessSyms = new HashMap<Symbol,MethodSymbol[]>();
 3647               accessConstrs = new HashMap<Symbol,MethodSymbol>();
 3648               accessConstrTags = List.nil();
 3649               accessed = new ListBuffer<Symbol>();
 3650               translate(cdef, (JCExpression)null);
 3651               for (List<Symbol> l = accessed.toList(); l.nonEmpty(); l = l.tail)
 3652                   makeAccessible(l.head);
 3653               for (EnumMapping map : enumSwitchMap.values())
 3654                   map.translate();
 3655               checkConflicts(this.translated.toList());
 3656               checkAccessConstructorTags();
 3657               translated = this.translated;
 3658           } finally {
 3659               // note that recursive invocations of this method fail hard
 3660               attrEnv = null;
 3661               this.make = null;
 3662               endPositions = null;
 3663               currentClass = null;
 3664               currentMethodDef = null;
 3665               outermostClassDef = null;
 3666               outermostMemberDef = null;
 3667               this.translated = null;
 3668               classdefs = null;
 3669               actualSymbols = null;
 3670               freevarCache = null;
 3671               proxies = null;
 3672               outerThisStack = null;
 3673               accessNums = null;
 3674               accessSyms = null;
 3675               accessConstrs = null;
 3676               accessConstrTags = null;
 3677               accessed = null;
 3678               enumSwitchMap.clear();
 3679           }
 3680           return translated.toList();
 3681       }
 3682   
 3683       //////////////////////////////////////////////////////////////
 3684       // The following contributed by Borland for bootstrapping purposes
 3685       //////////////////////////////////////////////////////////////
 3686       private void addEnumCompatibleMembers(JCClassDecl cdef) {
 3687           make_at(null);
 3688   
 3689           // Add the special enum fields
 3690           VarSymbol ordinalFieldSym = addEnumOrdinalField(cdef);
 3691           VarSymbol nameFieldSym = addEnumNameField(cdef);
 3692   
 3693           // Add the accessor methods for name and ordinal
 3694           MethodSymbol ordinalMethodSym = addEnumFieldOrdinalMethod(cdef, ordinalFieldSym);
 3695           MethodSymbol nameMethodSym = addEnumFieldNameMethod(cdef, nameFieldSym);
 3696   
 3697           // Add the toString method
 3698           addEnumToString(cdef, nameFieldSym);
 3699   
 3700           // Add the compareTo method
 3701           addEnumCompareTo(cdef, ordinalFieldSym);
 3702       }
 3703   
 3704       private VarSymbol addEnumOrdinalField(JCClassDecl cdef) {
 3705           VarSymbol ordinal = new VarSymbol(PRIVATE|FINAL|SYNTHETIC,
 3706                                             names.fromString("$ordinal"),
 3707                                             syms.intType,
 3708                                             cdef.sym);
 3709           cdef.sym.members().enter(ordinal);
 3710           cdef.defs = cdef.defs.prepend(make.VarDef(ordinal, null));
 3711           return ordinal;
 3712       }
 3713   
 3714       private VarSymbol addEnumNameField(JCClassDecl cdef) {
 3715           VarSymbol name = new VarSymbol(PRIVATE|FINAL|SYNTHETIC,
 3716                                             names.fromString("$name"),
 3717                                             syms.stringType,
 3718                                             cdef.sym);
 3719           cdef.sym.members().enter(name);
 3720           cdef.defs = cdef.defs.prepend(make.VarDef(name, null));
 3721           return name;
 3722       }
 3723   
 3724       private MethodSymbol addEnumFieldOrdinalMethod(JCClassDecl cdef, VarSymbol ordinalSymbol) {
 3725           // Add the accessor methods for ordinal
 3726           Symbol ordinalSym = lookupMethod(cdef.pos(),
 3727                                            names.ordinal,
 3728                                            cdef.type,
 3729                                            List.<Type>nil());
 3730   
 3731           Assert.check(ordinalSym instanceof MethodSymbol);
 3732   
 3733           JCStatement ret = make.Return(make.Ident(ordinalSymbol));
 3734           cdef.defs = cdef.defs.append(make.MethodDef((MethodSymbol)ordinalSym,
 3735                                                       make.Block(0L, List.of(ret))));
 3736   
 3737           return (MethodSymbol)ordinalSym;
 3738       }
 3739   
 3740       private MethodSymbol addEnumFieldNameMethod(JCClassDecl cdef, VarSymbol nameSymbol) {
 3741           // Add the accessor methods for name
 3742           Symbol nameSym = lookupMethod(cdef.pos(),
 3743                                      names._name,
 3744                                      cdef.type,
 3745                                      List.<Type>nil());
 3746   
 3747           Assert.check(nameSym instanceof MethodSymbol);
 3748   
 3749           JCStatement ret = make.Return(make.Ident(nameSymbol));
 3750   
 3751           cdef.defs = cdef.defs.append(make.MethodDef((MethodSymbol)nameSym,
 3752                                                       make.Block(0L, List.of(ret))));
 3753   
 3754           return (MethodSymbol)nameSym;
 3755       }
 3756   
 3757       private MethodSymbol addEnumToString(JCClassDecl cdef,
 3758                                            VarSymbol nameSymbol) {
 3759           Symbol toStringSym = lookupMethod(cdef.pos(),
 3760                                             names.toString,
 3761                                             cdef.type,
 3762                                             List.<Type>nil());
 3763   
 3764           JCTree toStringDecl = null;
 3765           if (toStringSym != null)
 3766               toStringDecl = TreeInfo.declarationFor(toStringSym, cdef);
 3767   
 3768           if (toStringDecl != null)
 3769               return (MethodSymbol)toStringSym;
 3770   
 3771           JCStatement ret = make.Return(make.Ident(nameSymbol));
 3772   
 3773           JCTree resTypeTree = make.Type(syms.stringType);
 3774   
 3775           MethodType toStringType = new MethodType(List.<Type>nil(),
 3776                                                    syms.stringType,
 3777                                                    List.<Type>nil(),
 3778                                                    cdef.sym);
 3779           toStringSym = new MethodSymbol(PUBLIC,
 3780                                          names.toString,
 3781                                          toStringType,
 3782                                          cdef.type.tsym);
 3783           toStringDecl = make.MethodDef((MethodSymbol)toStringSym,
 3784                                         make.Block(0L, List.of(ret)));
 3785   
 3786           cdef.defs = cdef.defs.prepend(toStringDecl);
 3787           cdef.sym.members().enter(toStringSym);
 3788   
 3789           return (MethodSymbol)toStringSym;
 3790       }
 3791   
 3792       private MethodSymbol addEnumCompareTo(JCClassDecl cdef, VarSymbol ordinalSymbol) {
 3793           Symbol compareToSym = lookupMethod(cdef.pos(),
 3794                                      names.compareTo,
 3795                                      cdef.type,
 3796                                      List.of(cdef.sym.type));
 3797   
 3798           Assert.check(compareToSym instanceof MethodSymbol);
 3799   
 3800           JCMethodDecl compareToDecl = (JCMethodDecl) TreeInfo.declarationFor(compareToSym, cdef);
 3801   
 3802           ListBuffer<JCStatement> blockStatements = new ListBuffer<JCStatement>();
 3803   
 3804           JCModifiers mod1 = make.Modifiers(0L);
 3805           Name oName = names.fromString("o");
 3806           JCVariableDecl par1 = make.Param(oName, cdef.type, compareToSym);
 3807   
 3808           JCIdent paramId1 = make.Ident(names.java_lang_Object);
 3809           paramId1.type = cdef.type;
 3810           paramId1.sym = par1.sym;
 3811   
 3812           ((MethodSymbol)compareToSym).params = List.of(par1.sym);
 3813   
 3814           JCIdent par1UsageId = make.Ident(par1.sym);
 3815           JCIdent castTargetIdent = make.Ident(cdef.sym);
 3816           JCTypeCast cast = make.TypeCast(castTargetIdent, par1UsageId);
 3817           cast.setType(castTargetIdent.type);
 3818   
 3819           Name otherName = names.fromString("other");
 3820   
 3821           VarSymbol otherVarSym = new VarSymbol(mod1.flags,
 3822                                                 otherName,
 3823                                                 cdef.type,
 3824                                                 compareToSym);
 3825           JCVariableDecl otherVar = make.VarDef(otherVarSym, cast);
 3826           blockStatements.append(otherVar);
 3827   
 3828           JCIdent id1 = make.Ident(ordinalSymbol);
 3829   
 3830           JCIdent fLocUsageId = make.Ident(otherVarSym);
 3831           JCExpression sel = make.Select(fLocUsageId, ordinalSymbol);
 3832           JCBinary bin = makeBinary(JCTree.MINUS, id1, sel);
 3833           JCReturn ret = make.Return(bin);
 3834           blockStatements.append(ret);
 3835           JCMethodDecl compareToMethod = make.MethodDef((MethodSymbol)compareToSym,
 3836                                                      make.Block(0L,
 3837                                                                 blockStatements.toList()));
 3838           compareToMethod.params = List.of(par1);
 3839           cdef.defs = cdef.defs.append(compareToMethod);
 3840   
 3841           return (MethodSymbol)compareToSym;
 3842       }
 3843       //////////////////////////////////////////////////////////////
 3844       // The above contributed by Borland for bootstrapping purposes
 3845       //////////////////////////////////////////////////////////////
 3846   }

Home » openjdk-7 » com.sun.tools » javac » comp » [javadoc | source]