1 /*
   2  * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.*;
  29 
  30 import com.sun.tools.javac.code.*;
  31 import com.sun.tools.javac.code.Symbol.*;
  32 import com.sun.tools.javac.tree.*;
  33 import com.sun.tools.javac.tree.JCTree.*;
  34 import com.sun.tools.javac.util.*;
  35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  36 import com.sun.tools.javac.util.List;
  37 
  38 import static com.sun.tools.javac.code.Flags.*;
  39 import static com.sun.tools.javac.code.Kinds.*;
  40 import static com.sun.tools.javac.code.TypeTag.CLASS;
  41 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
  42 import static com.sun.tools.javac.code.TypeTag.VOID;
  43 import static com.sun.tools.javac.comp.CompileStates.CompileState;
  44 
  45 /** This pass translates Generic Java to conventional Java.
  46  *
  47  *  <p><b>This is NOT part of any supported API.
  48  *  If you write code that depends on this, you do so at your own risk.
  49  *  This code and its internal interfaces are subject to change or
  50  *  deletion without notice.</b>
  51  */
  52 public class TransTypes extends TreeTranslator {
  53     /** The context key for the TransTypes phase. */
  54     protected static final Context.Key<TransTypes> transTypesKey =
  55         new Context.Key<TransTypes>();
  56 
  57     /** Get the instance for this context. */
  58     public static TransTypes instance(Context context) {
  59         TransTypes instance = context.get(transTypesKey);
  60         if (instance == null)
  61             instance = new TransTypes(context);
  62         return instance;
  63     }
  64 
  65     private Names names;
  66     private Log log;
  67     private Symtab syms;
  68     private TreeMaker make;
  69     private Enter enter;
  70     private boolean allowEnums;
  71     private boolean allowInterfaceBridges;
  72     private Types types;
  73     private final Resolve resolve;
  74 
  75     /**
  76      * Flag to indicate whether or not to generate bridge methods.
  77      * For pre-Tiger source there is no need for bridge methods, so it
  78      * can be skipped to get better performance for -source 1.4 etc.
  79      */
  80     private final boolean addBridges;
  81 
  82     private final CompileStates compileStates;
  83 
  84     protected TransTypes(Context context) {
  85         context.put(transTypesKey, this);
  86         compileStates = CompileStates.instance(context);
  87         names = Names.instance(context);
  88         log = Log.instance(context);
  89         syms = Symtab.instance(context);
  90         enter = Enter.instance(context);
  91         overridden = new HashMap<MethodSymbol,MethodSymbol>();
  92         Source source = Source.instance(context);
  93         allowEnums = source.allowEnums();
  94         addBridges = source.addBridges();
  95         allowInterfaceBridges = source.allowDefaultMethods();
  96         types = Types.instance(context);
  97         make = TreeMaker.instance(context);
  98         resolve = Resolve.instance(context);
  99     }
 100 
 101     /** A hashtable mapping bridge methods to the methods they override after
 102      *  type erasure.
 103      */
 104     Map<MethodSymbol,MethodSymbol> overridden;
 105 
 106     /** Construct an attributed tree for a cast of expression to target type,
 107      *  unless it already has precisely that type.
 108      *  @param tree    The expression tree.
 109      *  @param target  The target type.
 110      */
 111     JCExpression cast(JCExpression tree, Type target) {
 112         int oldpos = make.pos;
 113         make.at(tree.pos);
 114         if (!types.isSameType(tree.type, target)) {
 115             if (!resolve.isAccessible(env, target.tsym))
 116                 resolve.logAccessErrorInternal(env, tree, target);
 117             tree = make.TypeCast(make.Type(target), tree).setType(target);
 118         }
 119         make.pos = oldpos;
 120         return tree;
 121     }
 122 
 123     /** Construct an attributed tree to coerce an expression to some erased
 124      *  target type, unless the expression is already assignable to that type.
 125      *  If target type is a constant type, use its base type instead.
 126      *  @param tree    The expression tree.
 127      *  @param target  The target type.
 128      */
 129     public JCExpression coerce(Env<AttrContext> env, JCExpression tree, Type target) {
 130         Env<AttrContext> prevEnv = this.env;
 131         try {
 132             this.env = env;
 133             return coerce(tree, target);
 134         }
 135         finally {
 136             this.env = prevEnv;
 137         }
 138     }
 139     JCExpression coerce(JCExpression tree, Type target) {
 140         Type btarget = target.baseType();
 141         if (tree.type.isPrimitive() == target.isPrimitive()) {
 142             return types.isAssignable(tree.type, btarget, types.noWarnings)
 143                 ? tree
 144                 : cast(tree, btarget);
 145         }
 146         return tree;
 147     }
 148 
 149     /** Given an erased reference type, assume this type as the tree's type.
 150      *  Then, coerce to some given target type unless target type is null.
 151      *  This operation is used in situations like the following:
 152      *
 153      *  <pre>{@code
 154      *  class Cell<A> { A value; }
 155      *  ...
 156      *  Cell<Integer> cell;
 157      *  Integer x = cell.value;
 158      *  }</pre>
 159      *
 160      *  Since the erasure of Cell.value is Object, but the type
 161      *  of cell.value in the assignment is Integer, we need to
 162      *  adjust the original type of cell.value to Object, and insert
 163      *  a cast to Integer. That is, the last assignment becomes:
 164      *
 165      *  <pre>{@code
 166      *  Integer x = (Integer)cell.value;
 167      *  }</pre>
 168      *
 169      *  @param tree       The expression tree whose type might need adjustment.
 170      *  @param erasedType The expression's type after erasure.
 171      *  @param target     The target type, which is usually the erasure of the
 172      *                    expression's original type.
 173      */
 174     JCExpression retype(JCExpression tree, Type erasedType, Type target) {
 175 //      System.err.println("retype " + tree + " to " + erasedType);//DEBUG
 176         if (!erasedType.isPrimitive()) {
 177             if (target != null && target.isPrimitive()) {
 178                 target = erasure(tree.type);
 179             }
 180             tree.type = erasedType;
 181             if (target != null) {
 182                 return coerce(tree, target);
 183             }
 184         }
 185         return tree;
 186     }
 187 
 188     /** Translate method argument list, casting each argument
 189      *  to its corresponding type in a list of target types.
 190      *  @param _args            The method argument list.
 191      *  @param parameters       The list of target types.
 192      *  @param varargsElement   The erasure of the varargs element type,
 193      *  or null if translating a non-varargs invocation
 194      */
 195     <T extends JCTree> List<T> translateArgs(List<T> _args,
 196                                            List<Type> parameters,
 197                                            Type varargsElement) {
 198         if (parameters.isEmpty()) return _args;
 199         List<T> args = _args;
 200         while (parameters.tail.nonEmpty()) {
 201             args.head = translate(args.head, parameters.head);
 202             args = args.tail;
 203             parameters = parameters.tail;
 204         }
 205         Type parameter = parameters.head;
 206         Assert.check(varargsElement != null || args.length() == 1);
 207         if (varargsElement != null) {
 208             while (args.nonEmpty()) {
 209                 args.head = translate(args.head, varargsElement);
 210                 args = args.tail;
 211             }
 212         } else {
 213             args.head = translate(args.head, parameter);
 214         }
 215         return _args;
 216     }
 217 
 218     public <T extends JCTree> List<T> translateArgs(List<T> _args,
 219                                            List<Type> parameters,
 220                                            Type varargsElement,
 221                                            Env<AttrContext> localEnv) {
 222         Env<AttrContext> prevEnv = env;
 223         try {
 224             env = localEnv;
 225             return translateArgs(_args, parameters, varargsElement);
 226         }
 227         finally {
 228             env = prevEnv;
 229         }
 230     }
 231 
 232     /** Add a bridge definition and enter corresponding method symbol in
 233      *  local scope of origin.
 234      *
 235      *  @param pos     The source code position to be used for the definition.
 236      *  @param meth    The method for which a bridge needs to be added
 237      *  @param impl    That method's implementation (possibly the method itself)
 238      *  @param origin  The class to which the bridge will be added
 239      *  @param hypothetical
 240      *                 True if the bridge method is not strictly necessary in the
 241      *                 binary, but is represented in the symbol table to detect
 242      *                 erasure clashes.
 243      *  @param bridges The list buffer to which the bridge will be added
 244      */
 245     void addBridge(DiagnosticPosition pos,
 246                    MethodSymbol meth,
 247                    MethodSymbol impl,
 248                    ClassSymbol origin,
 249                    boolean hypothetical,
 250                    ListBuffer<JCTree> bridges) {
 251         make.at(pos);
 252         Type origType = types.memberType(origin.type, meth);
 253         Type origErasure = erasure(origType);
 254 
 255         // Create a bridge method symbol and a bridge definition without a body.
 256         Type bridgeType = meth.erasure(types);
 257         long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE |
 258                 (origin.isInterface() ? DEFAULT : 0);
 259         if (hypothetical) flags |= HYPOTHETICAL;
 260         MethodSymbol bridge = new MethodSymbol(flags,
 261                                                meth.name,
 262                                                bridgeType,
 263                                                origin);
 264         /* once JDK-6996415 is solved it should be checked if this approach can
 265          * be applied to method addOverrideBridgesIfNeeded
 266          */
 267         bridge.params = createBridgeParams(impl, bridge, bridgeType);
 268         bridge.setAttributes(impl);
 269 
 270         if (!hypothetical) {
 271             JCMethodDecl md = make.MethodDef(bridge, null);
 272 
 273             // The bridge calls this.impl(..), if we have an implementation
 274             // in the current class, super.impl(...) otherwise.
 275             JCExpression receiver = (impl.owner == origin)
 276                 ? make.This(origin.erasure(types))
 277                 : make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
 278 
 279             // The type returned from the original method.
 280             Type calltype = erasure(impl.type.getReturnType());
 281 
 282             // Construct a call of  this.impl(params), or super.impl(params),
 283             // casting params and possibly results as needed.
 284             JCExpression call =
 285                 make.Apply(
 286                            null,
 287                            make.Select(receiver, impl).setType(calltype),
 288                            translateArgs(make.Idents(md.params), origErasure.getParameterTypes(), null))
 289                 .setType(calltype);
 290             JCStatement stat = (origErasure.getReturnType().hasTag(VOID))
 291                 ? make.Exec(call)
 292                 : make.Return(coerce(call, bridgeType.getReturnType()));
 293             md.body = make.Block(0, List.of(stat));
 294 
 295             // Add bridge to `bridges' buffer
 296             bridges.append(md);
 297         }
 298 
 299         // Add bridge to scope of enclosing class and `overridden' table.
 300         origin.members().enter(bridge);
 301         overridden.put(bridge, meth);
 302     }
 303 
 304     private List<VarSymbol> createBridgeParams(MethodSymbol impl, MethodSymbol bridge,
 305             Type bridgeType) {
 306         List<VarSymbol> bridgeParams = null;
 307         if (impl.params != null) {
 308             bridgeParams = List.nil();
 309             List<VarSymbol> implParams = impl.params;
 310             Type.MethodType mType = (Type.MethodType)bridgeType;
 311             List<Type> argTypes = mType.argtypes;
 312             while (implParams.nonEmpty() && argTypes.nonEmpty()) {
 313                 VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER,
 314                         implParams.head.name, argTypes.head, bridge);
 315                 param.setAttributes(implParams.head);
 316                 bridgeParams = bridgeParams.append(param);
 317                 implParams = implParams.tail;
 318                 argTypes = argTypes.tail;
 319             }
 320         }
 321         return bridgeParams;
 322     }
 323 
 324     /** Add bridge if given symbol is a non-private, non-static member
 325      *  of the given class, which is either defined in the class or non-final
 326      *  inherited, and one of the two following conditions holds:
 327      *  1. The method's type changes in the given class, as compared to the
 328      *     class where the symbol was defined, (in this case
 329      *     we have extended a parameterized class with non-trivial parameters).
 330      *  2. The method has an implementation with a different erased return type.
 331      *     (in this case we have used co-variant returns).
 332      *  If a bridge already exists in some other class, no new bridge is added.
 333      *  Instead, it is checked that the bridge symbol overrides the method symbol.
 334      *  (Spec ???).
 335      *  todo: what about bridges for privates???
 336      *
 337      *  @param pos     The source code position to be used for the definition.
 338      *  @param sym     The symbol for which a bridge might have to be added.
 339      *  @param origin  The class in which the bridge would go.
 340      *  @param bridges The list buffer to which the bridge would be added.
 341      */
 342     void addBridgeIfNeeded(DiagnosticPosition pos,
 343                            Symbol sym,
 344                            ClassSymbol origin,
 345                            ListBuffer<JCTree> bridges) {
 346         if (sym.kind == MTH &&
 347             sym.name != names.init &&
 348             (sym.flags() & (PRIVATE | STATIC)) == 0 &&
 349             (sym.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC &&
 350             sym.isMemberOf(origin, types))
 351         {
 352             MethodSymbol meth = (MethodSymbol)sym;
 353             MethodSymbol bridge = meth.binaryImplementation(origin, types);
 354             MethodSymbol impl = meth.implementation(origin, types, true, overrideBridgeFilter);
 355             if (bridge == null ||
 356                 bridge == meth ||
 357                 (impl != null && !bridge.owner.isSubClass(impl.owner, types))) {
 358                 // No bridge was added yet.
 359                 if (impl != null && isBridgeNeeded(meth, impl, origin.type)) {
 360                     addBridge(pos, meth, impl, origin, bridge==impl, bridges);
 361                 } else if (impl == meth
 362                            && impl.owner != origin
 363                            && (impl.flags() & FINAL) == 0
 364                            && (meth.flags() & (ABSTRACT|PUBLIC)) == PUBLIC
 365                            && (origin.flags() & PUBLIC) > (impl.owner.flags() & PUBLIC)) {
 366                     // this is to work around a horrible but permanent
 367                     // reflection design error.
 368                     addBridge(pos, meth, impl, origin, false, bridges);
 369                 }
 370             } else if ((bridge.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) == SYNTHETIC) {
 371                 MethodSymbol other = overridden.get(bridge);
 372                 if (other != null && other != meth) {
 373                     if (impl == null || !impl.overrides(other, origin, types, true)) {
 374                         // Bridge for other symbol pair was added
 375                         log.error(pos, "name.clash.same.erasure.no.override",
 376                                   other, other.location(origin.type, types),
 377                                   meth,  meth.location(origin.type, types));
 378                     }
 379                 }
 380             } else if (!bridge.overrides(meth, origin, types, true)) {
 381                 // Accidental binary override without source override.
 382                 if (bridge.owner == origin ||
 383                     types.asSuper(bridge.owner.type, meth.owner) == null)
 384                     // Don't diagnose the problem if it would already
 385                     // have been reported in the superclass
 386                     log.error(pos, "name.clash.same.erasure.no.override",
 387                               bridge, bridge.location(origin.type, types),
 388                               meth,  meth.location(origin.type, types));
 389             }
 390         }
 391     }
 392     // where
 393         private Filter<Symbol> overrideBridgeFilter = new Filter<Symbol>() {
 394             public boolean accepts(Symbol s) {
 395                 return (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC;
 396             }
 397         };
 398 
 399         /**
 400          * @param method The symbol for which a bridge might have to be added
 401          * @param impl The implementation of method
 402          * @param dest The type in which the bridge would go
 403          */
 404         private boolean isBridgeNeeded(MethodSymbol method,
 405                                        MethodSymbol impl,
 406                                        Type dest) {
 407             if (impl != method) {
 408                 // If either method or impl have different erasures as
 409                 // members of dest, a bridge is needed.
 410                 Type method_erasure = method.erasure(types);
 411                 if (!isSameMemberWhenErased(dest, method, method_erasure))
 412                     return true;
 413                 Type impl_erasure = impl.erasure(types);
 414                 if (!isSameMemberWhenErased(dest, impl, impl_erasure))
 415                     return true;
 416 
 417                 // If the erasure of the return type is different, a
 418                 // bridge is needed.
 419                 return !types.isSameType(impl_erasure.getReturnType(),
 420                                          method_erasure.getReturnType());
 421             } else {
 422                // method and impl are the same...
 423                 if ((method.flags() & ABSTRACT) != 0) {
 424                     // ...and abstract so a bridge is not needed.
 425                     // Concrete subclasses will bridge as needed.
 426                     return false;
 427                 }
 428 
 429                 // The erasure of the return type is always the same
 430                 // for the same symbol.  Reducing the three tests in
 431                 // the other branch to just one:
 432                 return !isSameMemberWhenErased(dest, method, method.erasure(types));
 433             }
 434         }
 435         /**
 436          * Lookup the method as a member of the type.  Compare the
 437          * erasures.
 438          * @param type the class where to look for the method
 439          * @param method the method to look for in class
 440          * @param erasure the erasure of method
 441          */
 442         private boolean isSameMemberWhenErased(Type type,
 443                                                MethodSymbol method,
 444                                                Type erasure) {
 445             return types.isSameType(erasure(types.memberType(type, method)),
 446                                     erasure);
 447         }
 448 
 449     void addBridges(DiagnosticPosition pos,
 450                     TypeSymbol i,
 451                     ClassSymbol origin,
 452                     ListBuffer<JCTree> bridges) {
 453         for (Scope.Entry e = i.members().elems; e != null; e = e.sibling)
 454             addBridgeIfNeeded(pos, e.sym, origin, bridges);
 455         for (List<Type> l = types.interfaces(i.type); l.nonEmpty(); l = l.tail)
 456             addBridges(pos, l.head.tsym, origin, bridges);
 457     }
 458 
 459     /** Add all necessary bridges to some class appending them to list buffer.
 460      *  @param pos     The source code position to be used for the bridges.
 461      *  @param origin  The class in which the bridges go.
 462      *  @param bridges The list buffer to which the bridges are added.
 463      */
 464     void addBridges(DiagnosticPosition pos, ClassSymbol origin, ListBuffer<JCTree> bridges) {
 465         Type st = types.supertype(origin.type);
 466         while (st.hasTag(CLASS)) {
 467 //          if (isSpecialization(st))
 468             addBridges(pos, st.tsym, origin, bridges);
 469             st = types.supertype(st);
 470         }
 471         for (List<Type> l = types.interfaces(origin.type); l.nonEmpty(); l = l.tail)
 472 //          if (isSpecialization(l.head))
 473             addBridges(pos, l.head.tsym, origin, bridges);
 474     }
 475 
 476 /* ************************************************************************
 477  * Visitor methods
 478  *************************************************************************/
 479 
 480     /** Visitor argument: proto-type.
 481      */
 482     private Type pt;
 483 
 484     /** Visitor method: perform a type translation on tree.
 485      */
 486     public <T extends JCTree> T translate(T tree, Type pt) {
 487         Type prevPt = this.pt;
 488         try {
 489             this.pt = pt;
 490             return translate(tree);
 491         } finally {
 492             this.pt = prevPt;
 493         }
 494     }
 495 
 496     /** Visitor method: perform a type translation on list of trees.
 497      */
 498     public <T extends JCTree> List<T> translate(List<T> trees, Type pt) {
 499         Type prevPt = this.pt;
 500         List<T> res;
 501         try {
 502             this.pt = pt;
 503             res = translate(trees);
 504         } finally {
 505             this.pt = prevPt;
 506         }
 507         return res;
 508     }
 509 
 510     public void visitClassDef(JCClassDecl tree) {
 511         translateClass(tree.sym);
 512         result = tree;
 513     }
 514 
 515     JCTree currentMethod = null;
 516     public void visitMethodDef(JCMethodDecl tree) {
 517         JCTree previousMethod = currentMethod;
 518         try {
 519             currentMethod = tree;
 520             tree.restype = translate(tree.restype, null);
 521             tree.typarams = List.nil();
 522             tree.params = translateVarDefs(tree.params);
 523             tree.recvparam = translate(tree.recvparam, null);
 524             tree.thrown = translate(tree.thrown, null);
 525             tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType());
 526             tree.type = erasure(tree.type);
 527             result = tree;
 528         } finally {
 529             currentMethod = previousMethod;
 530         }
 531 
 532         // Check that we do not introduce a name clash by erasing types.
 533         for (Scope.Entry e = tree.sym.owner.members().lookup(tree.name);
 534              e.sym != null;
 535              e = e.next()) {
 536             if (e.sym != tree.sym &&
 537                 types.isSameType(erasure(e.sym.type), tree.type)) {
 538                 log.error(tree.pos(),
 539                           "name.clash.same.erasure", tree.sym,
 540                           e.sym);
 541                 return;
 542             }
 543         }
 544     }
 545 
 546     public void visitVarDef(JCVariableDecl tree) {
 547         tree.vartype = translate(tree.vartype, null);
 548         tree.init = translate(tree.init, tree.sym.erasure(types));
 549         tree.type = erasure(tree.type);
 550         result = tree;
 551     }
 552 
 553     public void visitDoLoop(JCDoWhileLoop tree) {
 554         tree.body = translate(tree.body);
 555         tree.cond = translate(tree.cond, syms.booleanType);
 556         result = tree;
 557     }
 558 
 559     public void visitWhileLoop(JCWhileLoop tree) {
 560         tree.cond = translate(tree.cond, syms.booleanType);
 561         tree.body = translate(tree.body);
 562         result = tree;
 563     }
 564 
 565     public void visitForLoop(JCForLoop tree) {
 566         tree.init = translate(tree.init, null);
 567         if (tree.cond != null)
 568             tree.cond = translate(tree.cond, syms.booleanType);
 569         tree.step = translate(tree.step, null);
 570         tree.body = translate(tree.body);
 571         result = tree;
 572     }
 573 
 574     public void visitForeachLoop(JCEnhancedForLoop tree) {
 575         tree.var = translate(tree.var, null);
 576         Type iterableType = tree.expr.type;
 577         tree.expr = translate(tree.expr, erasure(tree.expr.type));
 578         if (types.elemtype(tree.expr.type) == null)
 579             tree.expr.type = iterableType; // preserve type for Lower
 580         tree.body = translate(tree.body);
 581         result = tree;
 582     }
 583 
 584     public void visitLambda(JCLambda tree) {
 585         JCTree prevMethod = currentMethod;
 586         try {
 587             currentMethod = null;
 588             tree.params = translate(tree.params);
 589             tree.body = translate(tree.body, tree.body.type==null? null : erasure(tree.body.type));
 590             tree.type = erasure(tree.type);
 591             result = tree;
 592         }
 593         finally {
 594             currentMethod = prevMethod;
 595         }
 596     }
 597 
 598     public void visitSwitch(JCSwitch tree) {
 599         Type selsuper = types.supertype(tree.selector.type);
 600         boolean enumSwitch = selsuper != null &&
 601             selsuper.tsym == syms.enumSym;
 602         Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
 603         tree.selector = translate(tree.selector, target);
 604         tree.cases = translateCases(tree.cases);
 605         result = tree;
 606     }
 607 
 608     public void visitCase(JCCase tree) {
 609         tree.pat = translate(tree.pat, null);
 610         tree.stats = translate(tree.stats);
 611         result = tree;
 612     }
 613 
 614     public void visitSynchronized(JCSynchronized tree) {
 615         tree.lock = translate(tree.lock, erasure(tree.lock.type));
 616         tree.body = translate(tree.body);
 617         result = tree;
 618     }
 619 
 620     public void visitTry(JCTry tree) {
 621         tree.resources = translate(tree.resources, syms.autoCloseableType);
 622         tree.body = translate(tree.body);
 623         tree.catchers = translateCatchers(tree.catchers);
 624         tree.finalizer = translate(tree.finalizer);
 625         result = tree;
 626     }
 627 
 628     public void visitConditional(JCConditional tree) {
 629         tree.cond = translate(tree.cond, syms.booleanType);
 630         tree.truepart = translate(tree.truepart, erasure(tree.type));
 631         tree.falsepart = translate(tree.falsepart, erasure(tree.type));
 632         tree.type = erasure(tree.type);
 633         result = retype(tree, tree.type, pt);
 634     }
 635 
 636    public void visitIf(JCIf tree) {
 637         tree.cond = translate(tree.cond, syms.booleanType);
 638         tree.thenpart = translate(tree.thenpart);
 639         tree.elsepart = translate(tree.elsepart);
 640         result = tree;
 641     }
 642 
 643     public void visitExec(JCExpressionStatement tree) {
 644         tree.expr = translate(tree.expr, null);
 645         result = tree;
 646     }
 647 
 648     public void visitReturn(JCReturn tree) {
 649         tree.expr = translate(tree.expr, currentMethod != null ? types.erasure(currentMethod.type).getReturnType() : null);
 650         result = tree;
 651     }
 652 
 653     public void visitThrow(JCThrow tree) {
 654         tree.expr = translate(tree.expr, erasure(tree.expr.type));
 655         result = tree;
 656     }
 657 
 658     public void visitAssert(JCAssert tree) {
 659         tree.cond = translate(tree.cond, syms.booleanType);
 660         if (tree.detail != null)
 661             tree.detail = translate(tree.detail, erasure(tree.detail.type));
 662         result = tree;
 663     }
 664 
 665     public void visitApply(JCMethodInvocation tree) {
 666         tree.meth = translate(tree.meth, null);
 667         Symbol meth = TreeInfo.symbol(tree.meth);
 668         Type mt = meth.erasure(types);
 669         List<Type> argtypes = mt.getParameterTypes();
 670         if (allowEnums &&
 671             meth.name==names.init &&
 672             meth.owner == syms.enumSym)
 673             argtypes = argtypes.tail.tail;
 674         if (tree.varargsElement != null)
 675             tree.varargsElement = types.erasure(tree.varargsElement);
 676         else
 677             if (tree.args.length() != argtypes.length()) {
 678                 log.error(tree.pos(),
 679                               "method.invoked.with.incorrect.number.arguments",
 680                               tree.args.length(), argtypes.length());
 681             }
 682         tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);
 683 
 684         tree.type = types.erasure(tree.type);
 685         // Insert casts of method invocation results as needed.
 686         result = retype(tree, mt.getReturnType(), pt);
 687     }
 688 
 689     public void visitNewClass(JCNewClass tree) {
 690         if (tree.encl != null)
 691             tree.encl = translate(tree.encl, erasure(tree.encl.type));
 692         tree.clazz = translate(tree.clazz, null);
 693         if (tree.varargsElement != null)
 694             tree.varargsElement = types.erasure(tree.varargsElement);
 695         tree.args = translateArgs(
 696             tree.args, tree.constructor.erasure(types).getParameterTypes(), tree.varargsElement);
 697         tree.def = translate(tree.def, null);
 698         if (tree.constructorType != null)
 699             tree.constructorType = erasure(tree.constructorType);
 700         tree.type = erasure(tree.type);
 701         result = tree;
 702     }
 703 
 704     public void visitNewArray(JCNewArray tree) {
 705         tree.elemtype = translate(tree.elemtype, null);
 706         translate(tree.dims, syms.intType);
 707         if (tree.type != null) {
 708             tree.elems = translate(tree.elems, erasure(types.elemtype(tree.type)));
 709             tree.type = erasure(tree.type);
 710         } else {
 711             tree.elems = translate(tree.elems, null);
 712         }
 713 
 714         result = tree;
 715     }
 716 
 717     public void visitParens(JCParens tree) {
 718         tree.expr = translate(tree.expr, pt);
 719         tree.type = erasure(tree.type);
 720         result = tree;
 721     }
 722 
 723     public void visitAssign(JCAssign tree) {
 724         tree.lhs = translate(tree.lhs, null);
 725         tree.rhs = translate(tree.rhs, erasure(tree.lhs.type));
 726         tree.type = erasure(tree.lhs.type);
 727         result = retype(tree, tree.type, pt);
 728     }
 729 
 730     public void visitAssignop(JCAssignOp tree) {
 731         tree.lhs = translate(tree.lhs, null);
 732         tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
 733         tree.type = erasure(tree.type);
 734         result = tree;
 735     }
 736 
 737     public void visitUnary(JCUnary tree) {
 738         tree.arg = translate(tree.arg, tree.operator.type.getParameterTypes().head);
 739         result = tree;
 740     }
 741 
 742     public void visitBinary(JCBinary tree) {
 743         tree.lhs = translate(tree.lhs, tree.operator.type.getParameterTypes().head);
 744         tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
 745         result = tree;
 746     }
 747 
 748     public void visitTypeCast(JCTypeCast tree) {
 749         tree.clazz = translate(tree.clazz, null);
 750         Type originalTarget = tree.type;
 751         tree.type = erasure(tree.type);
 752         tree.expr = translate(tree.expr, tree.type);
 753         if (originalTarget.isIntersection()) {
 754             Type.IntersectionClassType ict = (Type.IntersectionClassType)originalTarget;
 755             for (Type c : ict.getExplicitComponents()) {
 756                 Type ec = erasure(c);
 757                 if (!types.isSameType(ec, tree.type)) {
 758                     tree.expr = coerce(tree.expr, ec);
 759                 }
 760             }
 761         }
 762         result = tree;
 763     }
 764 
 765     public void visitTypeTest(JCInstanceOf tree) {
 766         tree.expr = translate(tree.expr, null);
 767         tree.clazz = translate(tree.clazz, null);
 768         result = tree;
 769     }
 770 
 771     public void visitIndexed(JCArrayAccess tree) {
 772         tree.indexed = translate(tree.indexed, erasure(tree.indexed.type));
 773         tree.index = translate(tree.index, syms.intType);
 774 
 775         // Insert casts of indexed expressions as needed.
 776         result = retype(tree, types.elemtype(tree.indexed.type), pt);
 777     }
 778 
 779     // There ought to be nothing to rewrite here;
 780     // we don't generate code.
 781     public void visitAnnotation(JCAnnotation tree) {
 782         result = tree;
 783     }
 784 
 785     public void visitIdent(JCIdent tree) {
 786         Type et = tree.sym.erasure(types);
 787 
 788         // Map type variables to their bounds.
 789         if (tree.sym.kind == TYP && tree.sym.type.hasTag(TYPEVAR)) {
 790             result = make.at(tree.pos).Type(et);
 791         } else
 792         // Map constants expressions to themselves.
 793         if (tree.type.constValue() != null) {
 794             result = tree;
 795         }
 796         // Insert casts of variable uses as needed.
 797         else if (tree.sym.kind == VAR) {
 798             result = retype(tree, et, pt);
 799         }
 800         else {
 801             tree.type = erasure(tree.type);
 802             result = tree;
 803         }
 804     }
 805 
 806     public void visitSelect(JCFieldAccess tree) {
 807         Type t = tree.selected.type;
 808         while (t.hasTag(TYPEVAR))
 809             t = t.getUpperBound();
 810         if (t.isCompound()) {
 811             if ((tree.sym.flags() & IPROXY) != 0) {
 812                 tree.sym = ((MethodSymbol)tree.sym).
 813                     implemented((TypeSymbol)tree.sym.owner, types);
 814             }
 815             tree.selected = coerce(
 816                 translate(tree.selected, erasure(tree.selected.type)),
 817                 erasure(tree.sym.owner.type));
 818         } else
 819             tree.selected = translate(tree.selected, erasure(t));
 820 
 821         // Map constants expressions to themselves.
 822         if (tree.type.constValue() != null) {
 823             result = tree;
 824         }
 825         // Insert casts of variable uses as needed.
 826         else if (tree.sym.kind == VAR) {
 827             result = retype(tree, tree.sym.erasure(types), pt);
 828         }
 829         else {
 830             tree.type = erasure(tree.type);
 831             result = tree;
 832         }
 833     }
 834 
 835     public void visitReference(JCMemberReference tree) {
 836         tree.expr = translate(tree.expr, erasure(tree.expr.type));
 837         tree.type = erasure(tree.type);
 838         if (tree.varargsElement != null)
 839             tree.varargsElement = erasure(tree.varargsElement);
 840         result = tree;
 841     }
 842 
 843     public void visitTypeArray(JCArrayTypeTree tree) {
 844         tree.elemtype = translate(tree.elemtype, null);
 845         tree.type = erasure(tree.type);
 846         result = tree;
 847     }
 848 
 849     /** Visitor method for parameterized types.
 850      */
 851     public void visitTypeApply(JCTypeApply tree) {
 852         JCTree clazz = translate(tree.clazz, null);
 853         result = clazz;
 854     }
 855 
 856     public void visitTypeIntersection(JCTypeIntersection tree) {
 857         tree.bounds = translate(tree.bounds, null);
 858         tree.type = erasure(tree.type);
 859         result = tree;
 860     }
 861 
 862 /**************************************************************************
 863  * utility methods
 864  *************************************************************************/
 865 
 866     private Type erasure(Type t) {
 867         return types.erasure(t);
 868     }
 869 
 870     private boolean boundsRestricted(ClassSymbol c) {
 871         Type st = types.supertype(c.type);
 872         if (st.isParameterized()) {
 873             List<Type> actuals = st.allparams();
 874             List<Type> formals = st.tsym.type.allparams();
 875             while (!actuals.isEmpty() && !formals.isEmpty()) {
 876                 Type actual = actuals.head;
 877                 Type formal = formals.head;
 878 
 879                 if (!types.isSameType(types.erasure(actual),
 880                         types.erasure(formal)))
 881                     return true;
 882 
 883                 actuals = actuals.tail;
 884                 formals = formals.tail;
 885             }
 886         }
 887         return false;
 888     }
 889 
 890     private List<JCTree> addOverrideBridgesIfNeeded(DiagnosticPosition pos,
 891                                     final ClassSymbol c) {
 892         ListBuffer<JCTree> buf = new ListBuffer<>();
 893         if (c.isInterface() || !boundsRestricted(c))
 894             return buf.toList();
 895         Type t = types.supertype(c.type);
 896             Scope s = t.tsym.members();
 897             if (s.elems != null) {
 898                 for (Symbol sym : s.getElements(new NeedsOverridBridgeFilter(c))) {
 899 
 900                     MethodSymbol m = (MethodSymbol)sym;
 901                     MethodSymbol member = (MethodSymbol)m.asMemberOf(c.type, types);
 902                     MethodSymbol impl = m.implementation(c, types, false);
 903 
 904                     if ((impl == null || impl.owner != c) &&
 905                             !types.isSameType(member.erasure(types), m.erasure(types))) {
 906                         addOverrideBridges(pos, m, member, c, buf);
 907                     }
 908                 }
 909             }
 910         return buf.toList();
 911     }
 912     // where
 913         class NeedsOverridBridgeFilter implements Filter<Symbol> {
 914 
 915             ClassSymbol c;
 916 
 917             NeedsOverridBridgeFilter(ClassSymbol c) {
 918                 this.c = c;
 919             }
 920             public boolean accepts(Symbol s) {
 921                 return s.kind == MTH &&
 922                             !s.isConstructor() &&
 923                             s.isInheritedIn(c, types) &&
 924                             (s.flags() & FINAL) == 0 &&
 925                             (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC;
 926             }
 927         }
 928 
 929     private void addOverrideBridges(DiagnosticPosition pos,
 930                                     MethodSymbol impl,
 931                                     MethodSymbol member,
 932                                     ClassSymbol c,
 933                                     ListBuffer<JCTree> bridges) {
 934         Type implErasure = impl.erasure(types);
 935         long flags = (impl.flags() & AccessFlags) | SYNTHETIC | BRIDGE | OVERRIDE_BRIDGE;
 936         member = new MethodSymbol(flags, member.name, member.type, c);
 937         JCMethodDecl md = make.MethodDef(member, null);
 938         JCExpression receiver = make.Super(types.supertype(c.type).tsym.erasure(types), c);
 939         Type calltype = erasure(impl.type.getReturnType());
 940         JCExpression call =
 941             make.Apply(null,
 942                        make.Select(receiver, impl).setType(calltype),
 943                        translateArgs(make.Idents(md.params),
 944                                      implErasure.getParameterTypes(), null))
 945             .setType(calltype);
 946         JCStatement stat = (member.getReturnType().hasTag(VOID))
 947             ? make.Exec(call)
 948             : make.Return(coerce(call, member.erasure(types).getReturnType()));
 949         md.body = make.Block(0, List.of(stat));
 950         c.members().enter(member);
 951         bridges.append(md);
 952     }
 953 
 954 /**************************************************************************
 955  * main method
 956  *************************************************************************/
 957 
 958     private Env<AttrContext> env;
 959 
 960     private static final String statePreviousToFlowAssertMsg =
 961             "The current compile state [%s] of class %s is previous to FLOW";
 962 
 963     void translateClass(ClassSymbol c) {
 964         Type st = types.supertype(c.type);
 965         // process superclass before derived
 966         if (st.hasTag(CLASS)) {
 967             translateClass((ClassSymbol)st.tsym);
 968         }
 969 
 970         Env<AttrContext> myEnv = enter.getEnv(c);
 971         if (myEnv == null || (c.flags_field & TYPE_TRANSLATED) != 0) {
 972             return;
 973         }
 974         c.flags_field |= TYPE_TRANSLATED;
 975 
 976         /*  The two assertions below are set for early detection of any attempt
 977          *  to translate a class that:
 978          *
 979          *  1) has no compile state being it the most outer class.
 980          *     We accept this condition for inner classes.
 981          *
 982          *  2) has a compile state which is previous to Flow state.
 983          */
 984         boolean envHasCompState = compileStates.get(myEnv) != null;
 985         if (!envHasCompState && c.outermostClass() == c) {
 986             Assert.error("No info for outermost class: " + myEnv.enclClass.sym);
 987         }
 988 
 989         if (envHasCompState &&
 990                 CompileState.FLOW.isAfter(compileStates.get(myEnv))) {
 991             Assert.error(String.format(statePreviousToFlowAssertMsg,
 992                     compileStates.get(myEnv), myEnv.enclClass.sym));
 993         }
 994 
 995         Env<AttrContext> oldEnv = env;
 996         try {
 997             env = myEnv;
 998             // class has not been translated yet
 999 
1000             TreeMaker savedMake = make;
1001             Type savedPt = pt;
1002             make = make.forToplevel(env.toplevel);
1003             pt = null;
1004             try {
1005                 JCClassDecl tree = (JCClassDecl) env.tree;
1006                 tree.typarams = List.nil();
1007                 super.visitClassDef(tree);
1008                 make.at(tree.pos);
1009                 if (addBridges) {
1010                     ListBuffer<JCTree> bridges = new ListBuffer<JCTree>();
1011                     if (false) //see CR: 6996415
1012                         bridges.appendList(addOverrideBridgesIfNeeded(tree, c));
1013                     if (allowInterfaceBridges || (tree.sym.flags() & INTERFACE) == 0) {
1014                         addBridges(tree.pos(), c, bridges);
1015                     }
1016                     tree.defs = bridges.toList().prependList(tree.defs);
1017                 }
1018                 tree.type = erasure(tree.type);
1019             } finally {
1020                 make = savedMake;
1021                 pt = savedPt;
1022             }
1023         } finally {
1024             env = oldEnv;
1025         }
1026     }
1027 
1028     /** Translate a toplevel class definition.
1029      *  @param cdef    The definition to be translated.
1030      */
1031     public JCTree translateTopLevelClass(JCTree cdef, TreeMaker make) {
1032         // note that this method does NOT support recursion.
1033         this.make = make;
1034         pt = null;
1035         return translate(cdef, null);
1036     }
1037 }