diff -r f91144b7da75 -r af8417e590f4 src/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Feb 04 18:08:53 2013 -0500 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Sun Feb 17 16:44:55 2013 -0500 @@ -570,10 +570,19 @@ * @param flags The class symbol's flags * @param owner The class symbol's owner */ - ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) { + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner) { + return makeEmptyClass(flags, owner, null, true); + } + + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner, Name flatname, + boolean addToDefs) { // Create class symbol. ClassSymbol c = reader.defineClass(names.empty, owner); - c.flatname = chk.localClassName(c); + if (flatname != null) { + c.flatname = flatname; + } else { + c.flatname = chk.localClassName(c); + } c.sourcefile = owner.sourcefile; c.completer = null; c.members_field = new Scope(c); @@ -597,9 +606,8 @@ cdef.type = c.type; // Append class definition tree to owner's definitions. - odef.defs = odef.defs.prepend(cdef); - - return c; + if (addToDefs) odef.defs = odef.defs.prepend(cdef); + return cdef; } /************************************************************************** @@ -706,7 +714,7 @@ * and synthethise a class (with makeEmptyClass) if one is not available. * However, there is a small possibility that an existing class will not * be generated as expected if it is inside a conditional with a constant - * expression. If that is found to be the case, create an empty class here. + * expression. If that is found to be the case, create an empty class tree here. */ private void checkAccessConstructorTags() { for (List l = accessConstrTags; l.nonEmpty(); l = l.tail) { @@ -714,14 +722,10 @@ if (isTranslatedClassAvailable(c)) continue; // Create class definition tree. - JCClassDecl cdef = make.ClassDef( - make.Modifiers(STATIC | SYNTHETIC), names.empty, - List.nil(), - null, List.nil(), List.nil()); - cdef.sym = c; - cdef.type = c.type; - // add it to the list of classes to be generated - translated.append(cdef); + JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC, + c.outermostClass(), c.flatname, false); + swapAccessConstructorTag(c, cdec.sym); + translated.append(cdec); } } // where @@ -735,6 +739,19 @@ return false; } + void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) { + for (MethodSymbol methodSymbol : accessConstrs.values()) { + Assert.check(methodSymbol.type.hasTag(METHOD)); + MethodType oldMethodType = + (MethodType)methodSymbol.type; + if (oldMethodType.argtypes.head.tsym == oldCTag) + methodSymbol.type = + types.createMethodTypeWithParameters(oldMethodType, + oldMethodType.getParameterTypes().tail + .prepend(newCTag.erasure(types))); + } + } + /************************************************************************** * Access methods *************************************************************************/ @@ -1211,7 +1228,7 @@ "1"); ClassSymbol ctag = chk.compiled.get(flatname); if (ctag == null) - ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); + ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym; // keep a record of all tags, to verify that all are generated as required accessConstrTags = accessConstrTags.prepend(ctag); return ctag; @@ -1428,22 +1445,49 @@ return result; } + private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) { + if (owner.kind == TYP && + target.usePrivateSyntheticFields()) + flags |= PRIVATE; + Type target = types.erasure(owner.enclClass().type.getEnclosingType()); + VarSymbol outerThis = + new VarSymbol(flags, outerThisName(target, owner), target, owner); + outerThisStack = outerThisStack.prepend(outerThis); + return outerThis; + } + + private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) { + JCVariableDecl vd = make.at(pos).VarDef(sym, null); + vd.vartype = access(vd.vartype); + return vd; + } + + /** Definition for this$n field. + * @param pos The source code position of the definition. + * @param owner The method in which the definition goes. + */ + JCVariableDecl outerThisDef(int pos, MethodSymbol owner) { + ClassSymbol c = owner.enclClass(); + boolean isMandated = + // Anonymous constructors + (owner.isConstructor() && owner.isAnonymous()) || + // Constructors of non-private inner member classes + (owner.isConstructor() && c.isInner() && + !c.isPrivate() && !c.isStatic()); + long flags = + FINAL | (isMandated ? MANDATED : SYNTHETIC); + VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags); + owner.extraParams = owner.extraParams.prepend(outerThis); + return makeOuterThisVarDecl(pos, outerThis); + } + /** 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, Symbol owner) { - long flags = FINAL | SYNTHETIC; - if (owner.kind == TYP && - target.usePrivateSyntheticFields()) - flags |= PRIVATE; - Type target = types.erasure(owner.enclClass().type.getEnclosingType()); - VarSymbol outerThis = new VarSymbol( - flags, outerThisName(target, owner), target, owner); - outerThisStack = outerThisStack.prepend(outerThis); - JCVariableDecl vd = make.at(pos).VarDef(outerThis, null); - vd.vartype = access(vd.vartype); - return vd; + 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, @@ -1778,7 +1822,7 @@ if (e.sym.kind == TYP && e.sym.name == names.empty && (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; - return makeEmptyClass(STATIC | SYNTHETIC, clazz); + return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym; } /** Return symbol for "class$" method. If there is no method definition @@ -2551,7 +2595,6 @@ "enum" + target.syntheticNameChar() + "name"), syms.stringType, tree.sym); nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC; - JCVariableDecl ordParam = make. Param(names.fromString(target.syntheticNameChar() + "enum" + target.syntheticNameChar() + @@ -2562,6 +2605,8 @@ tree.params = tree.params.prepend(ordParam).prepend(nameParam); MethodSymbol m = tree.sym; + m.extraParams = m.extraParams.prepend(ordParam.sym); + m.extraParams = m.extraParams.prepend(nameParam.sym); Type olderasure = m.erasure(types); m.erasure_field = new MethodType( olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType), @@ -3049,55 +3094,38 @@ } public void visitAssignop(final JCAssignOp tree) { - if (!tree.lhs.type.isPrimitive() && - tree.operator.type.getReturnType().isPrimitive()) { - // boxing required; need to rewrite as x = (unbox typeof x)(x op y); - // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) - // (but without recomputing x) - JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { - public JCTree build(final JCTree lhs) { - JCTree.Tag newTag = tree.getTag().noAssignOp(); - // Erasure (TransTypes) can change the type of - // tree.lhs. However, we can still get the - // unerased type of tree.lhs as it is stored - // in tree.type in Attr. - Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), - newTag, - attrEnv, - tree.type, - tree.rhs.type); - JCExpression expr = (JCExpression)lhs; - if (expr.type != tree.type) - expr = make.TypeCast(tree.type, expr); - JCBinary opResult = make.Binary(newTag, expr, tree.rhs); - opResult.operator = newOperator; - opResult.type = newOperator.type.getReturnType(); - JCTypeCast newRhs = make.TypeCast(types.unboxedType(tree.type), - opResult); - return make.Assign((JCExpression)lhs, newRhs).setType(tree.type); - } - }); - result = translate(newTree); - return; - } - tree.lhs = translate(tree.lhs, tree); - tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); - - // If translated left hand side 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.lhs.hasTag(APPLY)) { - JCMethodInvocation app = (JCMethodInvocation)tree.lhs; - // if operation is a += on strings, - // make sure to convert argument to string - JCExpression rhs = (((OperatorSymbol)tree.operator).opcode == string_add) - ? makeString(tree.rhs) - : tree.rhs; - app.args = List.of(rhs).prependList(app.args); - result = app; - } else { - result = tree; - } + final boolean boxingReq = !tree.lhs.type.isPrimitive() && + tree.operator.type.getReturnType().isPrimitive(); + + // boxing required; need to rewrite as x = (unbox typeof x)(x op y); + // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) + // (but without recomputing x) + JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { + public JCTree build(final JCTree lhs) { + JCTree.Tag newTag = tree.getTag().noAssignOp(); + // Erasure (TransTypes) can change the type of + // tree.lhs. However, we can still get the + // unerased type of tree.lhs as it is stored + // in tree.type in Attr. + Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), + newTag, + attrEnv, + tree.type, + tree.rhs.type); + JCExpression expr = (JCExpression)lhs; + if (expr.type != tree.type) + expr = make.TypeCast(tree.type, expr); + JCBinary opResult = make.Binary(newTag, expr, tree.rhs); + opResult.operator = newOperator; + opResult.type = newOperator.type.getReturnType(); + JCExpression newRhs = boxingReq ? + make.TypeCast(types.unboxedType(tree.type), + opResult) : + opResult; + return make.Assign((JCExpression)lhs, newRhs).setType(tree.type); + } + }); + result = translate(newTree); } /** Lower a tree of the form e++ or e-- where e is an object type */