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

COVERAGE SUMMARY FOR SOURCE FILE [TransTypes.java]

nameclass, %method, %block, %line, %
TransTypes.java100% (1/1)58%  (29/50)46%  (956/2084)54%  (180.7/337)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class TransTypes100% (1/1)58%  (29/50)46%  (956/2084)54%  (180.7/337)
addBridge (JCDiagnostic$DiagnosticPosition, Symbol$MethodSymbol, Symbol$Metho... 0%   (0/1)0%   (0/151)0%   (0/18)
visitAnnotation (JCTree$JCAnnotation): void 0%   (0/1)0%   (0/4)0%   (0/2)
visitAssert (JCTree$JCAssert): void 0%   (0/1)0%   (0/29)0%   (0/5)
visitAssignop (JCTree$JCAssignOp): void 0%   (0/1)0%   (0/30)0%   (0/5)
visitBinary (JCTree$JCBinary): void 0%   (0/1)0%   (0/31)0%   (0/4)
visitCase (JCTree$JCCase): void 0%   (0/1)0%   (0/18)0%   (0/4)
visitConditional (JCTree$JCConditional): void 0%   (0/1)0%   (0/42)0%   (0/6)
visitDoLoop (JCTree$JCDoWhileLoop): void 0%   (0/1)0%   (0/21)0%   (0/4)
visitForLoop (JCTree$JCForLoop): void 0%   (0/1)0%   (0/38)0%   (0/7)
visitForeachLoop (JCTree$JCEnhancedForLoop): void 0%   (0/1)0%   (0/46)0%   (0/8)
visitIf (JCTree$JCIf): void 0%   (0/1)0%   (0/28)0%   (0/5)
visitIndexed (JCTree$JCArrayAccess): void 0%   (0/1)0%   (0/36)0%   (0/4)
visitNewArray (JCTree$JCNewArray): void 0%   (0/1)0%   (0/44)0%   (0/6)
visitSwitch (JCTree$JCSwitch): void 0%   (0/1)0%   (0/49)0%   (0/7)
visitSynchronized (JCTree$JCSynchronized): void 0%   (0/1)0%   (0/23)0%   (0/4)
visitThrow (JCTree$JCThrow): void 0%   (0/1)0%   (0/16)0%   (0/3)
visitTypeApply (JCTree$JCTypeApply): void 0%   (0/1)0%   (0/8)0%   (0/2)
visitTypeArray (JCTree$JCArrayTypeTree): void 0%   (0/1)0%   (0/18)0%   (0/4)
visitTypeTest (JCTree$JCInstanceOf): void 0%   (0/1)0%   (0/19)0%   (0/4)
visitUnary (JCTree$JCUnary): void 0%   (0/1)0%   (0/17)0%   (0/3)
visitWhileLoop (JCTree$JCWhileLoop): void 0%   (0/1)0%   (0/21)0%   (0/4)
isBridgeNeeded (Symbol$MethodSymbol, Symbol$MethodSymbol, Type): boolean 100% (1/1)33%  (21/63)26%  (2.8/11)
addBridgeIfNeeded (JCDiagnostic$DiagnosticPosition, Symbol, Symbol$ClassSymbo... 100% (1/1)37%  (86/235)43%  (7.7/18)
translateArgs (List, List, Type): List 100% (1/1)41%  (29/71)53%  (7.4/14)
visitSelect (JCTree$JCFieldAccess): void 100% (1/1)53%  (53/100)67%  (8.7/13)
addBridges (JCDiagnostic$DiagnosticPosition, Symbol$TypeSymbol, Symbol$ClassS... 100% (1/1)68%  (27/40)68%  (3.4/5)
visitMethodDef (JCTree$JCMethodDecl): void 100% (1/1)68%  (77/113)85%  (15.2/18)
visitNewClass (JCTree$JCNewClass): void 100% (1/1)71%  (46/65)80%  (8/10)
translate (JCTree, Type): JCTree 100% (1/1)71%  (15/21)93%  (3.7/4)
addBridges (JCDiagnostic$DiagnosticPosition, Symbol$ClassSymbol, ListBuffer):... 100% (1/1)72%  (33/46)77%  (5.4/7)
translate (List, Type): List 100% (1/1)73%  (16/22)95%  (5.7/6)
visitApply (JCTree$JCMethodInvocation): void 100% (1/1)73%  (59/81)76%  (9.2/12)
visitIdent (JCTree$JCIdent): void 100% (1/1)76%  (45/59)80%  (8/10)
retype (JCTree$JCExpression, Type, Type): JCTree$JCExpression 100% (1/1)81%  (21/26)83%  (5/6)
cast (JCTree$JCExpression, Type): JCTree$JCExpression 100% (1/1)86%  (42/49)88%  (7/8)
translateClass (Symbol$ClassSymbol): void 100% (1/1)88%  (112/127)95%  (26.6/28)
<static initializer> 100% (1/1)92%  (11/12)96%  (1.9/2)
coerce (JCTree$JCExpression, Type): JCTree$JCExpression 100% (1/1)92%  (24/26)75%  (3/4)
TransTypes (Context): void 100% (1/1)100% (54/54)100% (15/15)
erasure (Type): Type 100% (1/1)100% (5/5)100% (1/1)
instance (Context): TransTypes 100% (1/1)100% (14/14)100% (4/4)
isSameMemberWhenErased (Type, Symbol$MethodSymbol, Type): boolean 100% (1/1)100% (12/12)100% (1/1)
translateTopLevelClass (JCTree, TreeMaker): JCTree 100% (1/1)100% (11/11)100% (3/3)
visitAssign (JCTree$JCAssign): void 100% (1/1)100% (30/30)100% (5/5)
visitClassDef (JCTree$JCClassDecl): void 100% (1/1)100% (8/8)100% (3/3)
visitExec (JCTree$JCExpressionStatement): void 100% (1/1)100% (12/12)100% (3/3)
visitParens (JCTree$JCParens): void 100% (1/1)100% (19/19)100% (4/4)
visitReturn (JCTree$JCReturn): void 100% (1/1)100% (18/18)100% (3/3)
visitTypeCast (JCTree$JCTypeCast): void 100% (1/1)100% (26/26)100% (5/5)
visitVarDef (JCTree$JCVariableDecl): void 100% (1/1)100% (30/30)100% (5/5)

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.code.Symbol.*;
32import com.sun.tools.javac.tree.*;
33import com.sun.tools.javac.tree.JCTree.*;
34import com.sun.tools.javac.util.*;
35import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
36import com.sun.tools.javac.util.List;
37 
38import static com.sun.tools.javac.code.Flags.*;
39import static com.sun.tools.javac.code.Kinds.*;
40import static com.sun.tools.javac.code.TypeTags.*;
41 
42/** This pass translates Generic Java to conventional Java.
43 *
44 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
45 *  you write code that depends on this, you do so at your own risk.
46 *  This code and its internal interfaces are subject to change or
47 *  deletion without notice.</b>
48 */
49public class TransTypes extends TreeTranslator {
50    /** The context key for the TransTypes phase. */
51    protected static final Context.Key<TransTypes> transTypesKey =
52        new Context.Key<TransTypes>();
53 
54    /** Get the instance for this context. */
55    public static TransTypes instance(Context context) {
56        TransTypes instance = context.get(transTypesKey);
57        if (instance == null)
58            instance = new TransTypes(context);
59        return instance;
60    }
61 
62    private Name.Table names;
63    private Log log;
64    private Symtab syms;
65    private TreeMaker make;
66    private Enter enter;
67    private boolean allowEnums;
68    private Types types;
69    private final Resolve resolve;
70 
71    /**
72     * Flag to indicate whether or not to generate bridge methods.
73     * For pre-Tiger source there is no need for bridge methods, so it
74     * can be skipped to get better performance for -source 1.4 etc.
75     */
76    private final boolean addBridges;
77 
78    protected TransTypes(Context context) {
79        context.put(transTypesKey, this);
80        names = Name.Table.instance(context);
81        log = Log.instance(context);
82        syms = Symtab.instance(context);
83        enter = Enter.instance(context);
84        overridden = new HashMap<MethodSymbol,MethodSymbol>();
85        Source source = Source.instance(context);
86        allowEnums = source.allowEnums();
87        addBridges = source.addBridges();
88        types = Types.instance(context);
89        make = TreeMaker.instance(context);
90        resolve = Resolve.instance(context);
91    }
92 
93    /** A hashtable mapping bridge methods to the methods they override after
94     *  type erasure.
95     */
96    Map<MethodSymbol,MethodSymbol> overridden;
97 
98    /** Construct an attributed tree for a cast of expression to target type,
99     *  unless it already has precisely that type.
100     *  @param tree    The expression tree.
101     *  @param target  The target type.
102     */
103    JCExpression cast(JCExpression tree, Type target) {
104        int oldpos = make.pos;
105        make.at(tree.pos);
106        if (!types.isSameType(tree.type, target)) {
107            if (!resolve.isAccessible(env, target.tsym))
108                resolve.logAccessError(env, tree, target);
109            tree = make.TypeCast(make.Type(target), tree).setType(target);
110        }
111        make.pos = oldpos;
112        return tree;
113    }
114 
115    /** Construct an attributed tree to coerce an expression to some erased
116     *  target type, unless the expression is already assignable to that type.
117     *  If target type is a constant type, use its base type instead.
118     *  @param tree    The expression tree.
119     *  @param target  The target type.
120     */
121    JCExpression coerce(JCExpression tree, Type target) {
122        Type btarget = target.baseType();
123        if (tree.type.isPrimitive() == target.isPrimitive()) {
124            return types.isAssignable(tree.type, btarget, Warner.noWarnings)
125                ? tree
126                : cast(tree, btarget);
127        }
128        return tree;
129    }
130 
131    /** Given an erased reference type, assume this type as the tree's type.
132     *  Then, coerce to some given target type unless target type is null.
133     *  This operation is used in situations like the following:
134     *
135     *  class Cell<A> { A value; }
136     *  ...
137     *  Cell<Integer> cell;
138     *  Integer x = cell.value;
139     *
140     *  Since the erasure of Cell.value is Object, but the type
141     *  of cell.value in the assignment is Integer, we need to
142     *  adjust the original type of cell.value to Object, and insert
143     *  a cast to Integer. That is, the last assignment becomes:
144     *
145     *  Integer x = (Integer)cell.value;
146     *
147     *  @param tree       The expression tree whose type might need adjustment.
148     *  @param erasedType The expression's type after erasure.
149     *  @param target     The target type, which is usually the erasure of the
150     *                    expression's original type.
151     */
152    JCExpression retype(JCExpression tree, Type erasedType, Type target) {
153//      System.err.println("retype " + tree + " to " + erasedType);//DEBUG
154        if (erasedType.tag > lastBaseTag) {
155            if (target != null && target.isPrimitive())
156                target = erasure(tree.type);
157            tree.type = erasedType;
158            if (target != null) return coerce(tree, target);
159        }
160        return tree;
161    }
162 
163    /** Translate method argument list, casting each argument
164     *  to its corresponding type in a list of target types.
165     *  @param _args            The method argument list.
166     *  @param parameters       The list of target types.
167     *  @param varargsElement   The erasure of the varargs element type,
168     *  or null if translating a non-varargs invocation
169     */
170    <T extends JCTree> List<T> translateArgs(List<T> _args,
171                                           List<Type> parameters,
172                                           Type varargsElement) {
173        if (parameters.isEmpty()) return _args;
174        List<T> args = _args;
175        while (parameters.tail.nonEmpty()) {
176            args.head = translate(args.head, parameters.head);
177            args = args.tail;
178            parameters = parameters.tail;
179        }
180        Type parameter = parameters.head;
181        assert varargsElement != null || args.length() == 1;
182        if (varargsElement != null) {
183            while (args.nonEmpty()) {
184                args.head = translate(args.head, varargsElement);
185                args = args.tail;
186            }
187        } else {
188            args.head = translate(args.head, parameter);
189        }
190        return _args;
191    }
192 
193    /** Add a bridge definition and enter corresponding method symbol in
194     *  local scope of origin.
195     *
196     *  @param pos     The source code position to be used for the definition.
197     *  @param meth    The method for which a bridge needs to be added
198     *  @param impl    That method's implementation (possibly the method itself)
199     *  @param origin  The class to which the bridge will be added
200     *  @param hypothetical
201     *                 True if the bridge method is not strictly necessary in the
202     *                 binary, but is represented in the symbol table to detect
203     *                 erasure clashes.
204     *  @param bridges The list buffer to which the bridge will be added
205     */
206    void addBridge(DiagnosticPosition pos,
207                   MethodSymbol meth,
208                   MethodSymbol impl,
209                   ClassSymbol origin,
210                   boolean hypothetical,
211                   ListBuffer<JCTree> bridges) {
212        make.at(pos);
213        Type origType = types.memberType(origin.type, meth);
214        Type origErasure = erasure(origType);
215 
216        // Create a bridge method symbol and a bridge definition without a body.
217        Type bridgeType = meth.erasure(types);
218        long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE;
219        if (hypothetical) flags |= HYPOTHETICAL;
220        MethodSymbol bridge = new MethodSymbol(flags,
221                                               meth.name,
222                                               bridgeType,
223                                               origin);
224        if (!hypothetical) {
225            JCMethodDecl md = make.MethodDef(bridge, null);
226 
227            // The bridge calls this.impl(..), if we have an implementation
228            // in the current class, super.impl(...) otherwise.
229            JCExpression receiver = (impl.owner == origin)
230                ? make.This(origin.erasure(types))
231                : make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
232 
233            // The type returned from the original method.
234            Type calltype = erasure(impl.type.getReturnType());
235 
236            // Construct a call of  this.impl(params), or super.impl(params),
237            // casting params and possibly results as needed.
238            JCExpression call =
239                make.Apply(
240                           null,
241                           make.Select(receiver, impl).setType(calltype),
242                           translateArgs(make.Idents(md.params), origErasure.getParameterTypes(), null))
243                .setType(calltype);
244            JCStatement stat = (origErasure.getReturnType().tag == VOID)
245                ? make.Exec(call)
246                : make.Return(coerce(call, bridgeType.getReturnType()));
247            md.body = make.Block(0, List.of(stat));
248 
249            // Add bridge to `bridges' buffer
250            bridges.append(md);
251        }
252 
253        // Add bridge to scope of enclosing class and `overridden' table.
254        origin.members().enter(bridge);
255        overridden.put(bridge, meth);
256    }
257 
258    /** Add bridge if given symbol is a non-private, non-static member
259     *  of the given class, which is either defined in the class or non-final
260     *  inherited, and one of the two following conditions holds:
261     *  1. The method's type changes in the given class, as compared to the
262     *     class where the symbol was defined, (in this case
263     *     we have extended a parameterized class with non-trivial parameters).
264     *  2. The method has an implementation with a different erased return type.
265     *     (in this case we have used co-variant returns).
266     *  If a bridge already exists in some other class, no new bridge is added.
267     *  Instead, it is checked that the bridge symbol overrides the method symbol.
268     *  (Spec ???).
269     *  todo: what about bridges for privates???
270     *
271     *  @param pos     The source code position to be used for the definition.
272     *  @param sym     The symbol for which a bridge might have to be added.
273     *  @param origin  The class in which the bridge would go.
274     *  @param bridges The list buffer to which the bridge would be added.
275     */
276    void addBridgeIfNeeded(DiagnosticPosition pos,
277                           Symbol sym,
278                           ClassSymbol origin,
279                           ListBuffer<JCTree> bridges) {
280        if (sym.kind == MTH &&
281            sym.name != names.init &&
282            (sym.flags() & (PRIVATE | SYNTHETIC | STATIC)) == 0 &&
283            sym.isMemberOf(origin, types))
284        {
285            MethodSymbol meth = (MethodSymbol)sym;
286            MethodSymbol bridge = meth.binaryImplementation(origin, types);
287            MethodSymbol impl = meth.implementation(origin, types, true);
288            if (bridge == null ||
289                bridge == meth ||
290                (impl != null && !bridge.owner.isSubClass(impl.owner, types))) {
291                // No bridge was added yet.
292                if (impl != null && isBridgeNeeded(meth, impl, origin.type)) {
293                    addBridge(pos, meth, impl, origin, bridge==impl, bridges);
294                } else if (impl == meth
295                           && impl.owner != origin
296                           && (impl.flags() & FINAL) == 0
297                           && (meth.flags() & (ABSTRACT|PUBLIC)) == PUBLIC
298                           && (origin.flags() & PUBLIC) > (impl.owner.flags() & PUBLIC)) {
299                    // this is to work around a horrible but permanent
300                    // reflection design error.
301                    addBridge(pos, meth, impl, origin, false, bridges);
302                }
303            } else if ((bridge.flags() & SYNTHETIC) != 0) {
304                MethodSymbol other = overridden.get(bridge);
305                if (other != null && other != meth) {
306                    if (impl == null || !impl.overrides(other, origin, types, true)) {
307                        // Bridge for other symbol pair was added
308                        log.error(pos, "name.clash.same.erasure.no.override",
309                                  other, other.location(origin.type, types),
310                                  meth,  meth.location(origin.type, types));
311                    }
312                }
313            } else if (!bridge.overrides(meth, origin, types, true)) {
314                // Accidental binary override without source override.
315                if (bridge.owner == origin ||
316                    types.asSuper(bridge.owner.type, meth.owner) == null)
317                    // Don't diagnose the problem if it would already
318                    // have been reported in the superclass
319                    log.error(pos, "name.clash.same.erasure.no.override",
320                              bridge, bridge.location(origin.type, types),
321                              meth,  meth.location(origin.type, types));
322            }
323        }
324    }
325    // where
326        /**
327         * @param method The symbol for which a bridge might have to be added
328         * @param impl The implementation of method
329         * @param dest The type in which the bridge would go
330         */
331        private boolean isBridgeNeeded(MethodSymbol method,
332                                       MethodSymbol impl,
333                                       Type dest) {
334            if (impl != method) {
335                // If either method or impl have different erasures as
336                // members of dest, a bridge is needed.
337                Type method_erasure = method.erasure(types);
338                if (!isSameMemberWhenErased(dest, method, method_erasure))
339                    return true;
340                Type impl_erasure = impl.erasure(types);
341                if (!isSameMemberWhenErased(dest, impl, impl_erasure))
342                    return true;
343 
344                // If the erasure of the return type is different, a
345                // bridge is needed.
346                return !types.isSameType(impl_erasure.getReturnType(),
347                                         method_erasure.getReturnType());
348            } else {
349               // method and impl are the same...
350                if ((method.flags() & ABSTRACT) != 0) {
351                    // ...and abstract so a bridge is not needed.
352                    // Concrete subclasses will bridge as needed.
353                    return false;
354                }
355 
356                // The erasure of the return type is always the same
357                // for the same symbol.  Reducing the three tests in
358                // the other branch to just one:
359                return !isSameMemberWhenErased(dest, method, method.erasure(types));
360            }
361        }
362        /**
363         * Lookup the method as a member of the type.  Compare the
364         * erasures.
365         * @param type the class where to look for the method
366         * @param method the method to look for in class
367         * @param erasure the erasure of method
368         */
369        private boolean isSameMemberWhenErased(Type type,
370                                               MethodSymbol method,
371                                               Type erasure) {
372            return types.isSameType(erasure(types.memberType(type, method)),
373                                    erasure);
374        }
375 
376    void addBridges(DiagnosticPosition pos,
377                    TypeSymbol i,
378                    ClassSymbol origin,
379                    ListBuffer<JCTree> bridges) {
380        for (Scope.Entry e = i.members().elems; e != null; e = e.sibling)
381            addBridgeIfNeeded(pos, e.sym, origin, bridges);
382        for (List<Type> l = types.interfaces(i.type); l.nonEmpty(); l = l.tail)
383            addBridges(pos, l.head.tsym, origin, bridges);
384    }
385 
386    /** Add all necessary bridges to some class appending them to list buffer.
387     *  @param pos     The source code position to be used for the bridges.
388     *  @param origin  The class in which the bridges go.
389     *  @param bridges The list buffer to which the bridges are added.
390     */
391    void addBridges(DiagnosticPosition pos, ClassSymbol origin, ListBuffer<JCTree> bridges) {
392        Type st = types.supertype(origin.type);
393        while (st.tag == CLASS) {
394//          if (isSpecialization(st))
395            addBridges(pos, st.tsym, origin, bridges);
396            st = types.supertype(st);
397        }
398        for (List<Type> l = types.interfaces(origin.type); l.nonEmpty(); l = l.tail)
399//          if (isSpecialization(l.head))
400            addBridges(pos, l.head.tsym, origin, bridges);
401    }
402 
403/* ************************************************************************
404 * Visitor methods
405 *************************************************************************/
406 
407    /** Visitor argument: proto-type.
408     */
409    private Type pt;
410 
411    /** Visitor method: perform a type translation on tree.
412     */
413    public <T extends JCTree> T translate(T tree, Type pt) {
414        Type prevPt = this.pt;
415        try {
416            this.pt = pt;
417            return translate(tree);
418        } finally {
419            this.pt = prevPt;
420        }
421    }
422 
423    /** Visitor method: perform a type translation on list of trees.
424     */
425    public <T extends JCTree> List<T> translate(List<T> trees, Type pt) {
426        Type prevPt = this.pt;
427        List<T> res;
428        try {
429            this.pt = pt;
430            res = translate(trees);
431        } finally {
432            this.pt = prevPt;
433        }
434        return res;
435    }
436 
437    public void visitClassDef(JCClassDecl tree) {
438        translateClass(tree.sym);
439        result = tree;
440    }
441 
442    JCMethodDecl currentMethod = null;
443    public void visitMethodDef(JCMethodDecl tree) {
444        JCMethodDecl previousMethod = currentMethod;
445        try {
446            currentMethod = tree;
447            tree.restype = translate(tree.restype, null);
448            tree.typarams = List.nil();
449            tree.params = translateVarDefs(tree.params);
450            tree.thrown = translate(tree.thrown, null);
451            tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType());
452            tree.type = erasure(tree.type);
453            result = tree;
454        } finally {
455            currentMethod = previousMethod;
456        }
457 
458        // Check that we do not introduce a name clash by erasing types.
459        for (Scope.Entry e = tree.sym.owner.members().lookup(tree.name);
460             e.sym != null;
461             e = e.next()) {
462            if (e.sym != tree.sym &&
463                types.isSameType(erasure(e.sym.type), tree.type)) {
464                log.error(tree.pos(),
465                          "name.clash.same.erasure", tree.sym,
466                          e.sym);
467                return;
468            }
469        }
470    }
471 
472    public void visitVarDef(JCVariableDecl tree) {
473        tree.vartype = translate(tree.vartype, null);
474        tree.init = translate(tree.init, tree.sym.erasure(types));
475        tree.type = erasure(tree.type);
476        result = tree;
477    }
478 
479    public void visitDoLoop(JCDoWhileLoop tree) {
480        tree.body = translate(tree.body);
481        tree.cond = translate(tree.cond, syms.booleanType);
482        result = tree;
483    }
484 
485    public void visitWhileLoop(JCWhileLoop tree) {
486        tree.cond = translate(tree.cond, syms.booleanType);
487        tree.body = translate(tree.body);
488        result = tree;
489    }
490 
491    public void visitForLoop(JCForLoop tree) {
492        tree.init = translate(tree.init, null);
493        if (tree.cond != null)
494            tree.cond = translate(tree.cond, syms.booleanType);
495        tree.step = translate(tree.step, null);
496        tree.body = translate(tree.body);
497        result = tree;
498    }
499 
500    public void visitForeachLoop(JCEnhancedForLoop tree) {
501        tree.var = translate(tree.var, null);
502        Type iterableType = tree.expr.type;
503        tree.expr = translate(tree.expr, erasure(tree.expr.type));
504        if (types.elemtype(tree.expr.type) == null)
505            tree.expr.type = iterableType; // preserve type for Lower
506        tree.body = translate(tree.body);
507        result = tree;
508    }
509 
510    public void visitSwitch(JCSwitch tree) {
511        Type selsuper = types.supertype(tree.selector.type);
512        boolean enumSwitch = selsuper != null &&
513            selsuper.tsym == syms.enumSym;
514        Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
515        tree.selector = translate(tree.selector, target);
516        tree.cases = translateCases(tree.cases);
517        result = tree;
518    }
519 
520    public void visitCase(JCCase tree) {
521        tree.pat = translate(tree.pat, null);
522        tree.stats = translate(tree.stats);
523        result = tree;
524    }
525 
526    public void visitSynchronized(JCSynchronized tree) {
527        tree.lock = translate(tree.lock, erasure(tree.lock.type));
528        tree.body = translate(tree.body);
529        result = tree;
530    }
531 
532    public void visitConditional(JCConditional tree) {
533        tree.cond = translate(tree.cond, syms.booleanType);
534        tree.truepart = translate(tree.truepart, erasure(tree.type));
535        tree.falsepart = translate(tree.falsepart, erasure(tree.type));
536        tree.type = erasure(tree.type);
537        result = tree;
538    }
539 
540   public void visitIf(JCIf tree) {
541        tree.cond = translate(tree.cond, syms.booleanType);
542        tree.thenpart = translate(tree.thenpart);
543        tree.elsepart = translate(tree.elsepart);
544        result = tree;
545    }
546 
547    public void visitExec(JCExpressionStatement tree) {
548        tree.expr = translate(tree.expr, null);
549        result = tree;
550    }
551 
552    public void visitReturn(JCReturn tree) {
553        tree.expr = translate(tree.expr, currentMethod.sym.erasure(types).getReturnType());
554        result = tree;
555    }
556 
557    public void visitThrow(JCThrow tree) {
558        tree.expr = translate(tree.expr, erasure(tree.expr.type));
559        result = tree;
560    }
561 
562    public void visitAssert(JCAssert tree) {
563        tree.cond = translate(tree.cond, syms.booleanType);
564        if (tree.detail != null)
565            tree.detail = translate(tree.detail, erasure(tree.detail.type));
566        result = tree;
567    }
568 
569    public void visitApply(JCMethodInvocation tree) {
570        tree.meth = translate(tree.meth, null);
571        Symbol meth = TreeInfo.symbol(tree.meth);
572        Type mt = meth.erasure(types);
573        List<Type> argtypes = mt.getParameterTypes();
574        if (allowEnums &&
575            meth.name==names.init &&
576            meth.owner == syms.enumSym)
577            argtypes = argtypes.tail.tail;
578        if (tree.varargsElement != null)
579            tree.varargsElement = types.erasure(tree.varargsElement);
580        else
581            assert tree.args.length() == argtypes.length();
582        tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);
583 
584        // Insert casts of method invocation results as needed.
585        result = retype(tree, mt.getReturnType(), pt);
586    }
587 
588    public void visitNewClass(JCNewClass tree) {
589        if (tree.encl != null)
590            tree.encl = translate(tree.encl, erasure(tree.encl.type));
591        tree.clazz = translate(tree.clazz, null);
592        if (tree.varargsElement != null)
593            tree.varargsElement = types.erasure(tree.varargsElement);
594        tree.args = translateArgs(
595            tree.args, tree.constructor.erasure(types).getParameterTypes(), tree.varargsElement);
596        tree.def = translate(tree.def, null);
597        tree.type = erasure(tree.type);
598        result = tree;
599    }
600 
601    public void visitNewArray(JCNewArray tree) {
602        tree.elemtype = translate(tree.elemtype, null);
603        translate(tree.dims, syms.intType);
604        tree.elems = translate(tree.elems,
605                               (tree.type == null) ? null
606                               : erasure(types.elemtype(tree.type)));
607        tree.type = erasure(tree.type);
608 
609        result = tree;
610    }
611 
612    public void visitParens(JCParens tree) {
613        tree.expr = translate(tree.expr, pt);
614        tree.type = erasure(tree.type);
615        result = tree;
616    }
617 
618    public void visitAssign(JCAssign tree) {
619        tree.lhs = translate(tree.lhs, null);
620        tree.rhs = translate(tree.rhs, erasure(tree.lhs.type));
621        tree.type = erasure(tree.type);
622        result = tree;
623    }
624 
625    public void visitAssignop(JCAssignOp tree) {
626        tree.lhs = translate(tree.lhs, null);
627        tree.rhs = translate(tree.rhs, erasure(tree.rhs.type));
628        tree.type = erasure(tree.type);
629        result = tree;
630    }
631 
632    public void visitUnary(JCUnary tree) {
633        tree.arg = translate(tree.arg, tree.operator.type.getParameterTypes().head);
634        result = tree;
635    }
636 
637    public void visitBinary(JCBinary tree) {
638        tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head);
639        tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
640        result = tree;
641    }
642 
643    public void visitTypeCast(JCTypeCast tree) {
644        tree.clazz = translate(tree.clazz, null);
645        tree.type = erasure(tree.type);
646        tree.expr = translate(tree.expr, tree.type);
647        result = tree;
648    }
649 
650    public void visitTypeTest(JCInstanceOf tree) {
651        tree.expr = translate(tree.expr, null);
652        tree.clazz = translate(tree.clazz, null);
653        result = tree;
654    }
655 
656    public void visitIndexed(JCArrayAccess tree) {
657        tree.indexed = translate(tree.indexed, erasure(tree.indexed.type));
658        tree.index = translate(tree.index, syms.intType);
659 
660        // Insert casts of indexed expressions as needed.
661        result = retype(tree, types.elemtype(tree.indexed.type), pt);
662    }
663 
664    // There ought to be nothing to rewrite here;
665    // we don't generate code.
666    public void visitAnnotation(JCAnnotation tree) {
667        result = tree;
668    }
669 
670    public void visitIdent(JCIdent tree) {
671        Type et = tree.sym.erasure(types);
672 
673        // Map type variables to their bounds.
674        if (tree.sym.kind == TYP && tree.sym.type.tag == TYPEVAR) {
675            result = make.at(tree.pos).Type(et);
676        } else
677        // Map constants expressions to themselves.
678        if (tree.type.constValue() != null) {
679            result = tree;
680        }
681        // Insert casts of variable uses as needed.
682        else if (tree.sym.kind == VAR) {
683            result = retype(tree, et, pt);
684        }
685        else {
686            tree.type = erasure(tree.type);
687            result = tree;
688        }
689    }
690 
691    public void visitSelect(JCFieldAccess tree) {
692        Type t = tree.selected.type;
693        if (t.isCompound() || (t.tag == TYPEVAR && t.getUpperBound().isCompound())) {
694            if ((tree.sym.flags() & IPROXY) != 0) {
695                tree.sym = ((MethodSymbol)tree.sym).
696                    implemented((TypeSymbol)tree.sym.owner, types);
697            }
698            tree.selected = cast(
699                translate(tree.selected, erasure(t)),
700                erasure(tree.sym.owner.type));
701        } else
702            tree.selected = translate(tree.selected, erasure(t));
703 
704        // Map constants expressions to themselves.
705        if (tree.type.constValue() != null) {
706            result = tree;
707        }
708        // Insert casts of variable uses as needed.
709        else if (tree.sym.kind == VAR) {
710            result = retype(tree, tree.sym.erasure(types), pt);
711        }
712        else {
713            tree.type = erasure(tree.type);
714            result = tree;
715        }
716    }
717 
718    public void visitTypeArray(JCArrayTypeTree tree) {
719        tree.elemtype = translate(tree.elemtype, null);
720        tree.type = erasure(tree.type);
721        result = tree;
722    }
723 
724    /** Visitor method for parameterized types.
725     */
726    public void visitTypeApply(JCTypeApply tree) {
727        // Delete all type parameters.
728        result = translate(tree.clazz, null);
729    }
730 
731/**************************************************************************
732 * utility methods
733 *************************************************************************/
734 
735    private Type erasure(Type t) {
736        return types.erasure(t);
737    }
738 
739/**************************************************************************
740 * main method
741 *************************************************************************/
742 
743    private Env<AttrContext> env;
744 
745    void translateClass(ClassSymbol c) {
746        Type st = types.supertype(c.type);
747 
748        // process superclass before derived
749        if (st.tag == CLASS)
750            translateClass((ClassSymbol)st.tsym);
751 
752        Env<AttrContext> myEnv = enter.typeEnvs.remove(c);
753        if (myEnv == null)
754            return;
755        Env<AttrContext> oldEnv = env;
756        try {
757            env = myEnv;
758            // class has not been translated yet
759 
760            TreeMaker savedMake = make;
761            Type savedPt = pt;
762            make = make.forToplevel(env.toplevel);
763            pt = null;
764            try {
765                JCClassDecl tree = (JCClassDecl) env.tree;
766                tree.typarams = List.nil();
767                super.visitClassDef(tree);
768                make.at(tree.pos);
769                if (addBridges) {
770                    ListBuffer<JCTree> bridges = new ListBuffer<JCTree>();
771                    if ((tree.sym.flags() & INTERFACE) == 0)
772                        addBridges(tree.pos(), tree.sym, bridges);
773                    tree.defs = bridges.toList().prependList(tree.defs);
774                }
775                tree.type = erasure(tree.type);
776            } finally {
777                make = savedMake;
778                pt = savedPt;
779            }
780        } finally {
781            env = oldEnv;
782        }
783    }
784 
785    /** Translate a toplevel class definition.
786     *  @param cdef    The definition to be translated.
787     */
788    public JCTree translateTopLevelClass(JCTree cdef, TreeMaker make) {
789        // note that this method does NOT support recursion.
790        this.make = make;
791        pt = null;
792        return translate(cdef, null);
793    }
794}

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