diff -r 9f11c7676cd5 -r e9855150c5b0 src/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri May 31 10:04:59 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Sat Jun 01 21:57:56 2013 +0100 @@ -996,8 +996,9 @@ long ctorFlags = 0; boolean based = false; boolean addConstructor = true; + JCNewClass nc = null; if (c.name.isEmpty()) { - JCNewClass nc = (JCNewClass)env.next.tree; + nc = (JCNewClass)env.next.tree; if (nc.constructor != null) { addConstructor = nc.constructor.kind != ERR; Type superConstrType = types.memberType(c.type, @@ -1013,7 +1014,10 @@ } } if (addConstructor) { + MethodSymbol basedConstructor = nc != null ? + (MethodSymbol)nc.constructor : null; JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, + basedConstructor, typarams, argtypes, thrown, ctorFlags, based); tree.defs = tree.defs.prepend(constrDef); @@ -1399,34 +1403,78 @@ */ JCTree DefaultConstructor(TreeMaker make, ClassSymbol c, + MethodSymbol baseInit, List typarams, List argtypes, List thrown, long flags, boolean based) { - List params = make.Params(argtypes, syms.noSymbol); - List stats = List.nil(); - if (c.type != syms.objectType) - stats = stats.prepend(SuperCall(make, typarams, params, based)); + JCTree result; if ((c.flags() & ENUM) != 0 && (types.supertype(c.type).tsym == syms.enumSym)) { // constructors of true enums are private flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR; } else flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR; - if (c.name.isEmpty()) flags |= ANONCONSTR; - JCTree result = make.MethodDef( - make.Modifiers(flags), - names.init, - null, - make.TypeParams(typarams), - params, - make.Types(thrown), - make.Block(0, stats), - null); + if (c.name.isEmpty()) { + flags |= ANONCONSTR; + } + Type mType = new MethodType(argtypes, null, thrown, c); + Type initType = typarams.nonEmpty() ? + new ForAll(typarams, mType) : + mType; + MethodSymbol init = new MethodSymbol(flags, names.init, + initType, c); + init.params = createDefaultConstructorParams(make, baseInit, init, + argtypes, based); + List params = make.Params(argtypes, init); + List stats = List.nil(); + if (c.type != syms.objectType) { + stats = stats.prepend(SuperCall(make, typarams, params, based)); + } + result = make.MethodDef(init, make.Block(0, stats)); return result; } + private List createDefaultConstructorParams( + TreeMaker make, + MethodSymbol baseInit, + MethodSymbol init, + List argtypes, + boolean based) { + List initParams = null; + List argTypesList = argtypes; + if (based) { + /* In this case argtypes will have an extra type, compared to baseInit, + * corresponding to the type of the enclosing instance i.e.: + * + * Inner i = outer.new Inner(1){} + * + * in the above example argtypes will be (Outer, int) and baseInit + * will have parameter's types (int). So in this case we have to add + * first the extra type in argtypes and then get the names of the + * parameters from baseInit. + */ + initParams = List.nil(); + VarSymbol param = new VarSymbol(0, make.paramName(0), argtypes.head, init); + initParams = initParams.append(param); + argTypesList = argTypesList.tail; + } + if (baseInit != null && baseInit.params != null && + baseInit.params.nonEmpty() && argTypesList.nonEmpty()) { + initParams = (initParams == null) ? List.nil() : initParams; + List baseInitParams = baseInit.params; + while (baseInitParams.nonEmpty() && argTypesList.nonEmpty()) { + VarSymbol param = new VarSymbol(baseInitParams.head.flags(), + baseInitParams.head.name, argTypesList.head, init); + initParams = initParams.append(param); + baseInitParams = baseInitParams.tail; + argTypesList = argTypesList.tail; + } + } + return initParams; + } + /** Generate call to superclass constructor. This is: * * super(id_0, ..., id_n)