# HG changeset patch # User mcimadamore # Date 1305535084 -3600 # Node ID 5faa9eedc44e201f2b13ad837e9077668b823d28 # Parent 652f0daf74a72bd9a27bb088ebfcd49ef1ae0361 7043922: Regression: internal compiler error for nested anonymous inner class featuring varargs constructor Summary: Attributing a constructor call does not clean up the compiler's attribution context Reviewed-by: jjg diff -r 652f0daf74a7 -r 5faa9eedc44e src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Sat May 14 11:29:34 2011 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon May 16 09:38:04 2011 +0100 @@ -1708,20 +1708,24 @@ // that we are referring to a superclass instance of the // current instance (JLS ???). else { - localEnv.info.selectSuper = cdef != null; - localEnv.info.varArgs = false; + //the following code alters some of the fields in the current + //AttrContext - hence, the current context must be dup'ed in + //order to avoid downstream failures + Env rsEnv = localEnv.dup(tree); + rsEnv.info.selectSuper = cdef != null; + rsEnv.info.varArgs = false; tree.constructor = rs.resolveConstructor( - tree.pos(), localEnv, clazztype, argtypes, typeargtypes); + tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); tree.constructorType = tree.constructor.type.isErroneous() ? syms.errType : checkMethod(clazztype, tree.constructor, - localEnv, + rsEnv, tree.args, argtypes, typeargtypes, - localEnv.info.varArgs); - if (localEnv.info.varArgs) + rsEnv.info.varArgs); + if (rsEnv.info.varArgs) Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); } @@ -1779,9 +1783,10 @@ // Reassign clazztype and recompute constructor. clazztype = cdef.sym.type; + boolean useVarargs = tree.varargsElement != null; Symbol sym = rs.resolveConstructor( tree.pos(), localEnv, clazztype, argtypes, - typeargtypes, true, tree.varargsElement != null); + typeargtypes, true, useVarargs); Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous()); tree.constructor = sym; if (tree.constructor.kind > ERRONEOUS) { @@ -1794,7 +1799,7 @@ tree.args, argtypes, typeargtypes, - localEnv.info.varArgs); + useVarargs); } } diff -r 652f0daf74a7 -r 5faa9eedc44e test/tools/javac/varargs/7043922/T7043922.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/varargs/7043922/T7043922.java Mon May 16 09:38:04 2011 +0100 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7043922 + * @summary Regression: internal compiler error for nested anonymous inner class featuring varargs constructor + */ + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.List; + +import java.net.URI; +import java.util.Arrays; +import java.util.Locale; +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +public class T7043922 { + + ClassKind[] classKinds; + ConstructorKind[] constructorKinds; + + T7043922(ClassKind[] classKinds, ConstructorKind[] constructorKinds) { + this.classKinds = classKinds; + this.constructorKinds = constructorKinds; + } + + void compileAndCheck() throws Exception { + JavaSource source = new JavaSource(); + ErrorChecker ec = new ErrorChecker(); + JavacTask ct = (JavacTask)tool.getTask(null, fm, ec, + null, null, Arrays.asList(source)); + ct.analyze(); + if (ec.errorFound) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nCompiler diagnostics:\n" + ec.printDiags()); + } + } + + class JavaSource extends SimpleJavaFileObject { + + static final String source_template = "#C0 A0 { #K0 }\n" + + "#C1 A1 { #K1 }\n" + + "#C2 A2 { #K2 }\n" + + "class D {\n" + + " void test() {\n" + + " new A0(#V0) {\n" + + " void test() {\n" + + " new A1(#V1) {\n" + + " void test() {\n" + + " new A2(#V2) {};\n" + + " }\n" + + " };\n" + + " }\n" + + " };\n" + + " }\n" + + "}\n"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = source_template; + for (int i = 0; i < 3; i++) { + source = source.replaceAll("#C" + i, classKinds[i].classKind). + replaceAll("#K" + i, classKinds[i].getConstructor("A" + i, constructorKinds[i])). + replaceAll("#V" + i, constructorKinds[i].constrArgs); + } + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + /** global decls ***/ + + enum ConstructorKind { + DEFAULT("", ""), + FIXED_ARITY("String s", "\"\""), + VARIABLE_ARITY("String... ss", "\"\",\"\""); + + String constrParam; + String constrArgs; + + private ConstructorKind(String constrParam, String constrArgs) { + this.constrParam = constrParam; + this.constrArgs = constrArgs; + } + } + + enum ClassKind { + ABSTRACT("abstract class"), + CLASS("class"), + INTERFACE("interface"); + + String classKind; + + private ClassKind(String classKind) { + this.classKind = classKind; + } + + boolean isConstructorOk(ConstructorKind ck) { + return this != INTERFACE || + ck == ConstructorKind.DEFAULT; + } + + String getConstructor(String className, ConstructorKind ck) { + return this == INTERFACE ? + "" : + (className + "(" + ck.constrParam + ") {}"); + } + } + + // Create a single file manager and JavaCompiler tool + // and reuse them for each compile to save time. + static final StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); + static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + + public static void main(String... args) throws Exception { + for (ClassKind classKind1 : ClassKind.values()) { + for (ConstructorKind constrKind1 : ConstructorKind.values()) { + if (!classKind1.isConstructorOk(constrKind1)) continue; + for (ClassKind classKind2 : ClassKind.values()) { + for (ConstructorKind constrKind2 : ConstructorKind.values()) { + if (!classKind2.isConstructorOk(constrKind2)) continue; + for (ClassKind classKind3 : ClassKind.values()) { + for (ConstructorKind constrKind3 : ConstructorKind.values()) { + if (!classKind3.isConstructorOk(constrKind3)) continue; + new T7043922(new ClassKind[] { classKind1, classKind2, classKind3 }, + new ConstructorKind[] { constrKind1, constrKind2, constrKind3 }).compileAndCheck(); + } + } + } + } + } + } + } + + static class ErrorChecker implements javax.tools.DiagnosticListener { + + boolean errorFound; + List errDiags = List.nil(); + + public void report(Diagnostic diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errDiags = errDiags.append(diagnostic.getMessage(Locale.getDefault())); + errorFound = true; + } + } + + String printDiags() { + StringBuilder buf = new StringBuilder(); + for (String s : errDiags) { + buf.append(s); + buf.append("\n"); + } + return buf.toString(); + } + } +}