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