< prev index next > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
Print this page
for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
ClassSymbol c = l.head;
if (isTranslatedClassAvailable(c))
continue;
// Create class definition tree.
! JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC,
c.outermostClass(), c.flatname, false);
swapAccessConstructorTag(c, cdec.sym);
translated.append(cdec);
}
}
for (List<ClassSymbol> l = accessConstrTags; l.nonEmpty(); l = l.tail) {
ClassSymbol c = l.head;
if (isTranslatedClassAvailable(c))
continue;
// Create class definition tree.
! JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE,
c.outermostClass(), c.flatname, false);
swapAccessConstructorTag(c, cdec.sym);
translated.append(cdec);
}
}
}
JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
switch (sym.kind) {
case TYP:
if (sym.owner.kind != PCK) {
+ // Make sure not to lose type fidelity due to symbol sharing between projections
+ boolean requireReferenceProjection =
+ tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection();
// Convert type idents to
// <flat name> or <package name> . <flat name>
Name flatname = Convert.shortName(sym.flatName());
while (base != null &&
TreeInfo.symbol(base) != null &&
if (tree.hasTag(IDENT)) {
((JCIdent) tree).name = flatname;
} else if (base == null) {
tree = make.at(tree.pos).Ident(sym);
((JCIdent) tree).name = flatname;
+ if (requireReferenceProjection) {
+ tree.setType(tree.type.referenceProjection());
+ }
} else {
((JCFieldAccess) tree).selected = base;
((JCFieldAccess) tree).name = flatname;
+ if (requireReferenceProjection) {
+ tree.setType(tree.type.referenceProjection());
+ }
}
}
break;
case MTH: case VAR:
if (sym.owner.kind == TYP) {
Name flatname = names.fromString("" + topClass.getQualifiedName() +
target.syntheticNameChar() +
i);
ClassSymbol ctag = chk.getCompiled(topModle, flatname);
if (ctag == null)
! ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
else if (!ctag.isAnonymous())
continue;
// keep a record of all tags, to verify that all are generated as required
accessConstrTags = accessConstrTags.prepend(ctag);
return ctag;
Name flatname = names.fromString("" + topClass.getQualifiedName() +
target.syntheticNameChar() +
i);
ClassSymbol ctag = chk.getCompiled(topModle, flatname);
if (ctag == null)
! ctag = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, topClass).sym;
else if (!ctag.isAnonymous())
continue;
// keep a record of all tags, to verify that all are generated as required
accessConstrTags = accessConstrTags.prepend(ctag);
return ctag;
int index = 0;
Name proxyName;
do {
proxyName = proxyName(v.name, index++);
} while (!proxyNames.add(proxyName));
VarSymbol proxy = new VarSymbol(
! flags, proxyName, v.erasure(types), owner);
proxies.put(v, proxy);
JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
vd.vartype = access(vd.vartype);
defs = defs.prepend(vd);
}
int index = 0;
Name proxyName;
do {
proxyName = proxyName(v.name, index++);
} while (!proxyNames.add(proxyName));
+ final Type type = v.erasure(types);
VarSymbol proxy = new VarSymbol(
! flags, proxyName, type, owner);
proxies.put(v, proxy);
JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
vd.vartype = access(vd.vartype);
defs = defs.prepend(vd);
}
/** Definition for this$n field.
* @param pos The source code position of the definition.
* @param owner The class in which the definition goes.
*/
JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
! VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
return makeOuterThisVarDecl(pos, outerThis);
}
/** Return a list of trees that load the free variables in given list,
* in reverse order.
/** Definition for this$n field.
* @param pos The source code position of the definition.
* @param owner The class in which the definition goes.
*/
JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
! Type target = types.erasure(owner.enclClass().type.getEnclosingType());
+ long flags = FINAL | SYNTHETIC;
+ VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
return makeOuterThisVarDecl(pos, outerThis);
}
/** Return a list of trees that load the free variables in given list,
* in reverse order.
return newBlock;
}
private JCStatement makeResourceCloseInvocation(JCExpression resource) {
// convert to AutoCloseable if needed
! if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
resource = convert(resource, syms.autoCloseableType);
}
// create resource.close() method invocation
JCExpression resourceClose = makeCall(resource,
return newBlock;
}
private JCStatement makeResourceCloseInvocation(JCExpression resource) {
// convert to AutoCloseable if needed
! if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) {
resource = convert(resource, syms.autoCloseableType);
}
// create resource.close() method invocation
JCExpression resourceClose = makeCall(resource,
Scope s = clazz.members();
for (Symbol sym : s.getSymbols(NON_RECURSIVE))
if (sym.kind == TYP &&
sym.name == names.empty &&
(sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
! return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym;
}
/** Create an attributed tree of the form left.name(). */
private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
Assert.checkNonNull(left.type);
Scope s = clazz.members();
for (Symbol sym : s.getSymbols(NON_RECURSIVE))
if (sym.kind == TYP &&
sym.name == names.empty &&
(sym.flags() & INTERFACE) == 0) return (ClassSymbol) sym;
! return makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, clazz).sym;
}
/** Create an attributed tree of the form left.name(). */
private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
Assert.checkNonNull(left.type);
/**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
*/
private ClassSymbol assertionsDisabledClass() {
if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
! assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC, outermostClassDef.sym).sym;
return assertionsDisabledClassCache;
}
// This code is not particularly robust if the user has
/**Used to create an auxiliary class to hold $assertionsDisabled for interfaces.
*/
private ClassSymbol assertionsDisabledClass() {
if (assertionsDisabledClassCache != null) return assertionsDisabledClassCache;
! assertionsDisabledClassCache = makeEmptyClass(STATIC | SYNTHETIC | IDENTITY_TYPE, outermostClassDef.sym).sym;
return assertionsDisabledClassCache;
}
// This code is not particularly robust if the user has
}
/** Visitor method: Translate a single node, boxing or unboxing if needed.
*/
public <T extends JCExpression> T translate(T tree, Type type) {
! return (tree == null) ? null : boxIfNeeded(translate(tree), type);
}
/** Visitor method: Translate tree.
*/
public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
}
/** Visitor method: Translate a single node, boxing or unboxing if needed.
*/
public <T extends JCExpression> T translate(T tree, Type type) {
! return (tree == null) ? null :
+ applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
}
/** Visitor method: Translate tree.
*/
public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
seen = unseen;
}
// Convert a protected modifier to public, mask static modifier.
if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
! tree.mods.flags &= ClassFlags;
// Convert name to flat representation, replacing '.' by '$'.
tree.name = Convert.shortName(currentClass.flatName());
// Add free variables proxy definitions to class.
seen = unseen;
}
// Convert a protected modifier to public, mask static modifier.
if ((tree.mods.flags & PROTECTED) != 0) tree.mods.flags |= PUBLIC;
! tree.mods.flags &= AdjustedClassFlags;
// Convert name to flat representation, replacing '.' by '$'.
tree.name = Convert.shortName(currentClass.flatName());
// Add free variables proxy definitions to class.
if (!anyChanges) return _args;
}
return result.toList();
}
+ /** Apply primitive value/reference conversions as needed */
+ @SuppressWarnings("unchecked")
+ <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
+ boolean haveValue = tree.type.isPrimitiveClass();
+ if (haveValue == type.isPrimitiveClass())
+ return tree;
+ // For narrowing conversion, insert a cast which should trigger a null check
+ // For widening conversions, insert a cast if emitting a unified class file.
+ return (T) make.TypeCast(type, tree);
+
+ }
+
+
+
/** Expand a boxing or unboxing conversion if needed. */
@SuppressWarnings("unchecked") // XXX unchecked
<T extends JCExpression> T boxIfNeeded(T tree, Type type) {
boolean havePrimitive = tree.type.isPrimitive();
if (havePrimitive == type.isPrimitive())
* where #i is a freshly named synthetic local variable.
*/
private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
make_at(tree.expr.pos());
Type iteratorTarget = syms.objectType;
! Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
syms.iterableType.tsym);
if (iterableType.getTypeArguments().nonEmpty())
iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
Type eType = types.skipTypeVars(tree.expr.type, false);
tree.expr.type = types.erasure(eType);
* where #i is a freshly named synthetic local variable.
*/
private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
make_at(tree.expr.pos());
Type iteratorTarget = syms.objectType;
! Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()),
syms.iterableType.tsym);
if (iterableType.getTypeArguments().nonEmpty())
iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
Type eType = types.skipTypeVars(tree.expr.type, false);
tree.expr.type = types.erasure(eType);
Symbol iterator = lookupMethod(tree.expr.pos(),
names.iterator,
eType,
List.nil());
VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
! types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)),
currentMethodSym);
JCStatement init = make.
VarDef(itvar, make.App(make.Select(tree.expr, iterator)
.setType(types.erasure(iterator.type))));
Symbol iterator = lookupMethod(tree.expr.pos(),
names.iterator,
eType,
List.nil());
VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
! types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)),
currentMethodSym);
JCStatement init = make.
VarDef(itvar, make.App(make.Select(tree.expr, iterator)
.setType(types.erasure(iterator.type))));
tree.cond = translate(tree.cond, syms.booleanType);
tree.body = translate(tree.body);
result = tree;
}
+ public void visitWithField(JCWithField tree) {
+ Type fieldType = tree.field.type;
+ tree.field = translate(tree.field, tree);
+ tree.value = translate(tree.value, fieldType); // important to use pre-translation type.
+
+ // If translated field is an Apply, we are
+ // seeing an access method invocation. In this case, append
+ // right hand side as last argument of the access method.
+ if (tree.field.hasTag(APPLY)) {
+ JCMethodInvocation app = (JCMethodInvocation) tree.field;
+ app.args = List.of(tree.value).prependList(app.args);
+ result = app;
+ } else {
+ result = tree;
+ }
+ }
+
public void visitForLoop(JCForLoop tree) {
tree.init = translate(tree.init);
if (tree.cond != null)
tree.cond = translate(tree.cond, syms.booleanType);
tree.step = translate(tree.step);
// is a default interface subclassed by the current class.
boolean qualifiedSuperAccess =
tree.selected.hasTag(SELECT) &&
TreeInfo.name(tree.selected) == names._super &&
!types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
tree.selected = translate(tree.selected);
if (tree.name == names._class) {
result = classOf(tree.selected);
}
else if (tree.name == names._super &&
types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
//default super call!! Not a classic qualified super call
TypeSymbol supSym = tree.selected.type.tsym;
! Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
result = tree;
}
else if (tree.name == names._this || tree.name == names._super) {
result = makeThis(tree.pos(), tree.selected.type.tsym);
}
// is a default interface subclassed by the current class.
boolean qualifiedSuperAccess =
tree.selected.hasTag(SELECT) &&
TreeInfo.name(tree.selected) == names._super &&
!types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
+ /* JDK-8269956: Where a reflective (class) literal is needed, the unqualified Point.class is
+ * always the "primary" mirror - representing the primitive reference runtime type - thereby
+ * always matching the behavior of Object::getClass
+ */
+ boolean needPrimaryMirror = tree.name == names._class && tree.selected.type.isReferenceProjection();
tree.selected = translate(tree.selected);
+ if (needPrimaryMirror && tree.selected.type.isPrimitiveClass()) {
+ tree.selected.setType(tree.selected.type.referenceProjection());
+ }
if (tree.name == names._class) {
result = classOf(tree.selected);
}
else if (tree.name == names._super &&
types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
//default super call!! Not a classic qualified super call
TypeSymbol supSym = tree.selected.type.tsym;
! Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym));
result = tree;
}
else if (tree.name == names._this || tree.name == names._super) {
result = makeThis(tree.pos(), tree.selected.type.tsym);
}
< prev index next >