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