src/share/classes/com/sun/tools/javac/comp/TransTypes.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

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

mercurial