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