EMMA Coverage Report (generated Thu Dec 06 15:52:10 GMT 2007)
[all classes][com.sun.tools.javac.comp]

COVERAGE SUMMARY FOR SOURCE FILE [Lower.java]

nameclass, %method, %block, %line, %
Lower.java17%  (2/12)19%  (31/160)13%  (1190/8991)17%  (232.4/1344)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Lower$10%   (0/1)0%   (0/2)0%   (0/25)0%   (0/2)
Lower$1 (Lower, Lower$TreeBuilder, JCTree$JCFieldAccess): void 0%   (0/1)0%   (0/12)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/13)0%   (0/1)
     
class Lower$1Patcher0%   (0/1)0%   (0/4)0%   (0/33)0%   (0/8)
Lower$1Patcher (Lower, JCTree, JCTree): void 0%   (0/1)0%   (0/12)0%   (0/1)
visitBreak (JCTree$JCBreak): void 0%   (0/1)0%   (0/10)0%   (0/3)
visitClassDef (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/1)0%   (0/1)
visitContinue (JCTree$JCContinue): void 0%   (0/1)0%   (0/10)0%   (0/3)
     
class Lower$20%   (0/1)0%   (0/2)0%   (0/28)0%   (0/2)
Lower$2 (Lower, JCTree$JCArrayAccess, Lower$TreeBuilder): void 0%   (0/1)0%   (0/12)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/16)0%   (0/1)
     
class Lower$2$10%   (0/1)0%   (0/2)0%   (0/33)0%   (0/4)
Lower$2$1 (Lower$2, JCTree): void 0%   (0/1)0%   (0/9)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/24)0%   (0/3)
     
class Lower$30%   (0/1)0%   (0/2)0%   (0/12)0%   (0/2)
Lower$3 (Lower, JCTree): void 0%   (0/1)0%   (0/9)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/3)0%   (0/1)
     
class Lower$40%   (0/1)0%   (0/2)0%   (0/95)0%   (0/11)
Lower$4 (Lower, JCTree$JCAssignOp): void 0%   (0/1)0%   (0/9)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/86)0%   (0/10)
     
class Lower$50%   (0/1)0%   (0/2)0%   (0/26)0%   (0/2)
Lower$5 (Lower, JCTree$JCUnary, boolean): void 0%   (0/1)0%   (0/12)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/14)0%   (0/1)
     
class Lower$5$10%   (0/1)0%   (0/2)0%   (0/61)0%   (0/5)
Lower$5$1 (Lower$5, JCTree): void 0%   (0/1)0%   (0/9)0%   (0/1)
build (JCTree): JCTree 0%   (0/1)0%   (0/52)0%   (0/4)
     
class Lower$EnumMapping0%   (0/1)0%   (0/3)0%   (0/341)0%   (0/33)
Lower$EnumMapping (Lower, JCDiagnostic$DiagnosticPosition, Symbol$TypeSymbol)... 0%   (0/1)0%   (0/83)0%   (0/11)
forConstant (Symbol$VarSymbol): JCTree$JCLiteral 0%   (0/1)0%   (0/29)0%   (0/4)
translate (): void 0%   (0/1)0%   (0/229)0%   (0/18)
     
class Lower$FreeVarCollector0%   (0/1)0%   (0/8)0%   (0/251)0%   (0/47)
Lower$FreeVarCollector (Lower, Symbol$ClassSymbol): void 0%   (0/1)0%   (0/16)0%   (0/5)
addFreeVar (Symbol$VarSymbol): void 0%   (0/1)0%   (0/22)0%   (0/4)
addFreeVars (Symbol$ClassSymbol): void 0%   (0/1)0%   (0/24)0%   (0/5)
visitApply (JCTree$JCMethodInvocation): void 0%   (0/1)0%   (0/47)0%   (0/8)
visitIdent (JCTree$JCIdent): void 0%   (0/1)0%   (0/10)0%   (0/3)
visitNewClass (JCTree$JCNewClass): void 0%   (0/1)0%   (0/30)0%   (0/6)
visitSelect (JCTree$JCFieldAccess): void 0%   (0/1)0%   (0/37)0%   (0/4)
visitSymbol (Symbol): void 0%   (0/1)0%   (0/65)0%   (0/12)
     
class Lower100% (1/1)23%  (30/129)15%  (1184/8068)19%  (231.4/1231)
abstractLval (JCTree, Lower$TreeBuilder): JCTree 0%   (0/1)0%   (0/61)0%   (0/11)
abstractRval (JCTree, Lower$TreeBuilder): JCTree 0%   (0/1)0%   (0/7)0%   (0/1)
abstractRval (JCTree, Type, Lower$TreeBuilder): JCTree 0%   (0/1)0%   (0/81)0%   (0/12)
access (JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/14)0%   (0/2)
access$002 (Lower, JCTree): JCTree 0%   (0/1)0%   (0/5)0%   (0/1)
access$100 (Lower): Name$Table 0%   (0/1)0%   (0/3)0%   (0/1)
access$1000 (Lower): Types 0%   (0/1)0%   (0/3)0%   (0/1)
access$200 (Lower): Target 0%   (0/1)0%   (0/3)0%   (0/1)
access$300 (Lower): ClassWriter 0%   (0/1)0%   (0/3)0%   (0/1)
access$400 (Lower): Symbol$ClassSymbol 0%   (0/1)0%   (0/3)0%   (0/1)
access$500 (Lower): Symtab 0%   (0/1)0%   (0/3)0%   (0/1)
access$600 (Lower, JCDiagnostic$DiagnosticPosition, Symbol, Scope): void 0%   (0/1)0%   (0/6)0%   (0/1)
access$700 (Lower): TreeMaker 0%   (0/1)0%   (0/3)0%   (0/1)
access$800 (Lower, JCDiagnostic$DiagnosticPosition, Name, Type, List): Symbol... 0%   (0/1)0%   (0/7)0%   (0/1)
access$900 (Lower): Resolve 0%   (0/1)0%   (0/3)0%   (0/1)
accessBase (JCDiagnostic$DiagnosticPosition, Symbol): JCTree$JCExpression 0%   (0/1)0%   (0/24)0%   (0/1)
accessClass (Symbol, boolean, JCTree): Symbol$ClassSymbol 0%   (0/1)0%   (0/55)0%   (0/12)
accessCode (JCTree, JCTree): int 0%   (0/1)0%   (0/62)0%   (0/9)
accessConstructorDef (int, Symbol, Symbol$MethodSymbol): JCTree 0%   (0/1)0%   (0/53)0%   (0/7)
accessConstructorTag (): Symbol$ClassSymbol 0%   (0/1)0%   (0/39)0%   (0/6)
accessDef (int, Symbol, Symbol$MethodSymbol, int): JCTree 0%   (0/1)0%   (0/189)0%   (0/31)
accessName (int, int): Name 0%   (0/1)0%   (0/24)0%   (0/1)
accessSymbol (Symbol, JCTree, JCTree, boolean, boolean): Symbol$MethodSymbol 0%   (0/1)0%   (0/202)0%   (0/40)
addEnumCompareTo (JCTree$JCClassDecl, Symbol$VarSymbol): Symbol$MethodSymbol 0%   (0/1)0%   (0/183)0%   (0/30)
addEnumCompatibleMembers (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/33)0%   (0/8)
addEnumFieldNameMethod (JCTree$JCClassDecl, Symbol$VarSymbol): Symbol$MethodS... 0%   (0/1)0%   (0/55)0%   (0/6)
addEnumFieldOrdinalMethod (JCTree$JCClassDecl, Symbol$VarSymbol): Symbol$Meth... 0%   (0/1)0%   (0/55)0%   (0/6)
addEnumNameField (JCTree$JCClassDecl): Symbol$VarSymbol 0%   (0/1)0%   (0/31)0%   (0/4)
addEnumOrdinalField (JCTree$JCClassDecl): Symbol$VarSymbol 0%   (0/1)0%   (0/31)0%   (0/4)
addEnumToString (JCTree$JCClassDecl, Symbol$VarSymbol): Symbol$MethodSymbol 0%   (0/1)0%   (0/88)0%   (0/14)
assertFlagTest (JCDiagnostic$DiagnosticPosition): JCTree$JCExpression 0%   (0/1)0%   (0/101)0%   (0/14)
binaryAccessOperator (int): Symbol$OperatorSymbol 0%   (0/1)0%   (0/29)0%   (0/7)
boxPrimitive (JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/10)0%   (0/1)
boxPrimitive (JCTree$JCExpression, Type): JCTree$JCExpression 0%   (0/1)0%   (0/49)0%   (0/6)
cacheName (String): Name 0%   (0/1)0%   (0/68)0%   (0/11)
cacheSym (JCDiagnostic$DiagnosticPosition, String): Symbol$VarSymbol 0%   (0/1)0%   (0/53)0%   (0/10)
classDef (Symbol$ClassSymbol): JCTree$JCClassDecl 0%   (0/1)0%   (0/37)0%   (0/8)
classDollarSym (JCDiagnostic$DiagnosticPosition): Symbol$MethodSymbol 0%   (0/1)0%   (0/83)0%   (0/14)
classDollarSymBody (JCDiagnostic$DiagnosticPosition, JCTree$JCMethodDecl): JC... 0%   (0/1)0%   (0/349)0%   (0/28)
classOf (JCTree): JCTree$JCExpression 0%   (0/1)0%   (0/7)0%   (0/1)
classOfType (Type, JCDiagnostic$DiagnosticPosition): JCTree$JCExpression 0%   (0/1)0%   (0/146)0%   (0/13)
convert (JCTree, Type): JCTree 0%   (0/1)0%   (0/34)0%   (0/4)
duplicateError (JCDiagnostic$DiagnosticPosition, Symbol): void 0%   (0/1)0%   (0/21)0%   (0/3)
enterSynthetic (JCDiagnostic$DiagnosticPosition, Symbol, Scope): void 0%   (0/1)0%   (0/64)0%   (0/9)
initField (int, Name): JCTree$JCStatement 0%   (0/1)0%   (0/68)0%   (0/7)
initOuterThis (int): JCTree$JCStatement 0%   (0/1)0%   (0/67)0%   (0/6)
loadFreevar (JCDiagnostic$DiagnosticPosition, Symbol$VarSymbol): JCTree$JCExp... 0%   (0/1)0%   (0/12)0%   (0/1)
loadFreevars (JCDiagnostic$DiagnosticPosition, List): List 0%   (0/1)0%   (0/22)0%   (0/4)
lookupConstructor (JCDiagnostic$DiagnosticPosition, Type, List): Symbol$Metho... 0%   (0/1)0%   (0/10)0%   (0/1)
lookupField (JCDiagnostic$DiagnosticPosition, Type, Name): Symbol$VarSymbol 0%   (0/1)0%   (0/9)0%   (0/1)
lookupMethod (JCDiagnostic$DiagnosticPosition, Name, Type, List): Symbol$Meth... 0%   (0/1)0%   (0/11)0%   (0/1)
lookupSynthetic (Name, Scope): Symbol 0%   (0/1)0%   (0/18)0%   (0/2)
lowerBoxedPostop (JCTree$JCUnary): JCTree 0%   (0/1)0%   (0/29)0%   (0/3)
makeAccessible (Symbol): void 0%   (0/1)0%   (0/81)0%   (0/9)
makeAssignop (int, JCTree, JCTree): JCTree$JCAssignOp 0%   (0/1)0%   (0/30)0%   (0/4)
makeBinary (int, JCTree$JCExpression, JCTree$JCExpression): JCTree$JCBinary 0%   (0/1)0%   (0/29)0%   (0/4)
makeCall (JCTree$JCExpression, Name, List): JCTree$JCMethodInvocation 0%   (0/1)0%   (0/29)0%   (0/3)
makeComma (JCTree, JCTree): JCTree 0%   (0/1)0%   (0/9)0%   (0/1)
makeEmptyClass (long, Symbol$ClassSymbol): Symbol$ClassSymbol 0%   (0/1)0%   (0/91)0%   (0/17)
makeLit (Type, Object): JCTree$JCExpression 0%   (0/1)0%   (0/11)0%   (0/1)
makeNewClass (Type, List): JCTree$JCNewClass 0%   (0/1)0%   (0/33)0%   (0/4)
makeNull (): JCTree$JCExpression 0%   (0/1)0%   (0/7)0%   (0/1)
makeOuterThis (JCDiagnostic$DiagnosticPosition, Symbol$TypeSymbol): JCTree$JC... 0%   (0/1)0%   (0/118)0%   (0/23)
makeOwnerThis (JCDiagnostic$DiagnosticPosition, Symbol, boolean): JCTree$JCEx... 0%   (0/1)0%   (0/37)0%   (0/4)
makeOwnerThisN (JCDiagnostic$DiagnosticPosition, Symbol, boolean): JCTree$JCE... 0%   (0/1)0%   (0/112)0%   (0/20)
makeString (JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/31)0%   (0/4)
makeThis (JCDiagnostic$DiagnosticPosition, Symbol$TypeSymbol): JCTree$JCExpre... 0%   (0/1)0%   (0/19)0%   (0/3)
makeUnary (int, JCTree$JCExpression): JCTree$JCUnary 0%   (0/1)0%   (0/26)0%   (0/4)
mapForEnum (JCDiagnostic$DiagnosticPosition, Symbol$TypeSymbol): Lower$EnumMa... 0%   (0/1)0%   (0/23)0%   (0/4)
outerCacheClass (): Symbol$ClassSymbol 0%   (0/1)0%   (0/58)0%   (0/8)
outerThisDef (int, Symbol): JCTree$JCVariableDecl 0%   (0/1)0%   (0/55)0%   (0/9)
outerThisName (Type, Symbol): Name 0%   (0/1)0%   (0/59)0%   (0/9)
patchTargets (JCTree, JCTree, JCTree): void 0%   (0/1)0%   (0/9)0%   (0/2)
proxyName (Name): Name 0%   (0/1)0%   (0/16)0%   (0/1)
translate (List, JCTree$JCExpression): List 0%   (0/1)0%   (0/15)0%   (0/5)
translate (List, Type): List 0%   (0/1)0%   (0/23)0%   (0/4)
treeTag (Symbol$OperatorSymbol): int 0%   (0/1)0%   (0/29)0%   (0/13)
unbox (JCTree$JCExpression, Type): JCTree$JCExpression 0%   (0/1)0%   (0/35)0%   (0/4)
visitAnnotation (JCTree$JCAnnotation): void 0%   (0/1)0%   (0/4)0%   (0/2)
visitArrayForeachLoop (JCTree$JCEnhancedForLoop): void 0%   (0/1)0%   (0/203)0%   (0/17)
visitAssert (JCTree$JCAssert): void 0%   (0/1)0%   (0/80)0%   (0/11)
visitAssignop (JCTree$JCAssignOp): void 0%   (0/1)0%   (0/99)0%   (0/15)
visitBinary (JCTree$JCBinary): void 0%   (0/1)0%   (0/81)0%   (0/18)
visitConditional (JCTree$JCConditional): void 0%   (0/1)0%   (0/68)0%   (0/9)
visitDoLoop (JCTree$JCDoWhileLoop): void 0%   (0/1)0%   (0/21)0%   (0/4)
visitEnumConstantDef (JCTree$JCVariableDecl, int): void 0%   (0/1)0%   (0/26)0%   (0/3)
visitEnumDef (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/361)0%   (0/46)
visitEnumSwitch (JCTree$JCSwitch): JCTree 0%   (0/1)0%   (0/92)0%   (0/14)
visitForLoop (JCTree$JCForLoop): void 0%   (0/1)0%   (0/36)0%   (0/7)
visitForeachLoop (JCTree$JCEnhancedForLoop): void 0%   (0/1)0%   (0/15)0%   (0/4)
visitIf (JCTree$JCIf): void 0%   (0/1)0%   (0/61)0%   (0/11)
visitIndexed (JCTree$JCArrayAccess): void 0%   (0/1)0%   (0/21)0%   (0/4)
visitIterableForeachLoop (JCTree$JCEnhancedForLoop): void 0%   (0/1)0%   (0/217)0%   (0/23)
visitLetExpr (JCTree$LetExpr): void 0%   (0/1)0%   (0/18)0%   (0/4)
visitNewArray (JCTree$JCNewArray): void 0%   (0/1)0%   (0/45)0%   (0/6)
visitSwitch (JCTree$JCSwitch): void 0%   (0/1)0%   (0/66)0%   (0/10)
visitTopLevel (JCTree$JCCompilationUnit): void 0%   (0/1)0%   (0/102)0%   (0/20)
visitUnary (JCTree$JCUnary): void 0%   (0/1)0%   (0/110)0%   (0/17)
visitWhileLoop (JCTree$JCWhileLoop): void 0%   (0/1)0%   (0/21)0%   (0/4)
accessConstructor (JCDiagnostic$DiagnosticPosition, Symbol): Symbol 100% (1/1)7%   (6/86)15%  (2/13)
visitMethodDefInternal (JCTree$JCMethodDecl): void 100% (1/1)11%  (24/226)10%  (4/40)
needsProtectedAccess (Symbol, JCTree): boolean 100% (1/1)13%  (9/68)19%  (1.4/7)
visitMethodDef (JCTree$JCMethodDecl): void 100% (1/1)14%  (38/275)27%  (9.4/35)
boxIfNeeded (JCTree, Type): JCTree 100% (1/1)20%  (10/51)23%  (3/13)
freevars (Symbol$ClassSymbol): List 100% (1/1)21%  (8/38)22%  (2/9)
needsPrivateAccess (Symbol): boolean 100% (1/1)24%  (9/37)26%  (1.6/6)
access (Symbol, JCTree$JCExpression, JCTree$JCExpression, boolean): JCTree$JC... 100% (1/1)27%  (78/291)21%  (9.4/45)
freevarDefs (int, List, Symbol): List 100% (1/1)28%  (19/67)34%  (4.1/12)
boxArgs (List, List, Type): List 100% (1/1)36%  (51/142)38%  (11.4/30)
visitApply (JCTree$JCMethodInvocation): void 100% (1/1)41%  (97/238)47%  (18/38)
visitNewClass (JCTree$JCNewClass): void 100% (1/1)42%  (75/178)51%  (14.4/28)
visitBlock (JCTree$JCBlock): void 100% (1/1)46%  (13/28)83%  (5/6)
translate (JCTree): JCTree 100% (1/1)51%  (18/35)72%  (5.8/8)
visitSelect (JCTree$JCFieldAccess): void 100% (1/1)61%  (43/70)71%  (5.7/8)
visitAssign (JCTree$JCAssign): void 100% (1/1)63%  (27/43)56%  (5/9)
translateTopLevelClass (Env, JCTree, TreeMaker): List 100% (1/1)69%  (164/238)74%  (32.4/44)
accessCode (int): int 100% (1/1)71%  (29/41)57%  (4/7)
visitTypeCast (JCTree$JCTypeCast): void 100% (1/1)71%  (25/35)83%  (5/6)
visitClassDef (JCTree$JCClassDecl): void 100% (1/1)72%  (170/237)82%  (33.7/41)
translate (JCTree, Type): JCTree 100% (1/1)82%  (9/11)81%  (0.8/1)
visitVarDef (JCTree$JCVariableDecl): void 100% (1/1)84%  (48/57)92%  (8.2/9)
visitParens (JCTree$JCParens): void 100% (1/1)93%  (14/15)98%  (2.9/3)
<static initializer> 100% (1/1)94%  (16/17)98%  (2.9/3)
Lower (Context): void 100% (1/1)98%  (115/117)100% (23/23)
instance (Context): Lower 100% (1/1)100% (14/14)100% (4/4)
make_at (JCDiagnostic$DiagnosticPosition): TreeMaker 100% (1/1)100% (8/8)100% (2/2)
translate (JCTree, JCTree$JCExpression): JCTree 100% (1/1)100% (15/15)100% (5/5)
visitIdent (JCTree$JCIdent): void 100% (1/1)100% (11/11)100% (2/2)
visitReturn (JCTree$JCReturn): void 100% (1/1)100% (21/21)100% (4/4)
     
class Lower$ClassMap100% (1/1)50%  (1/2)33%  (6/18)25%  (1/4)
visitClassDef (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/12)0%   (0/3)
Lower$ClassMap (Lower): void 100% (1/1)100% (6/6)100% (1/1)

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

[all classes][com.sun.tools.javac.comp]
EMMA 2.0.5312 (C) Vladimir Roubtsov