Mon, 16 May 2011 09:38:04 +0100
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
src/share/classes/com/sun/tools/javac/comp/Attr.java | file | annotate | diff | comparison | revisions | |
test/tools/javac/varargs/7043922/T7043922.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Sat May 14 11:29:34 2011 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon May 16 09:38:04 2011 +0100 1.3 @@ -1708,20 +1708,24 @@ 1.4 // that we are referring to a superclass instance of the 1.5 // current instance (JLS ???). 1.6 else { 1.7 - localEnv.info.selectSuper = cdef != null; 1.8 - localEnv.info.varArgs = false; 1.9 + //the following code alters some of the fields in the current 1.10 + //AttrContext - hence, the current context must be dup'ed in 1.11 + //order to avoid downstream failures 1.12 + Env<AttrContext> rsEnv = localEnv.dup(tree); 1.13 + rsEnv.info.selectSuper = cdef != null; 1.14 + rsEnv.info.varArgs = false; 1.15 tree.constructor = rs.resolveConstructor( 1.16 - tree.pos(), localEnv, clazztype, argtypes, typeargtypes); 1.17 + tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); 1.18 tree.constructorType = tree.constructor.type.isErroneous() ? 1.19 syms.errType : 1.20 checkMethod(clazztype, 1.21 tree.constructor, 1.22 - localEnv, 1.23 + rsEnv, 1.24 tree.args, 1.25 argtypes, 1.26 typeargtypes, 1.27 - localEnv.info.varArgs); 1.28 - if (localEnv.info.varArgs) 1.29 + rsEnv.info.varArgs); 1.30 + if (rsEnv.info.varArgs) 1.31 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); 1.32 } 1.33 1.34 @@ -1779,9 +1783,10 @@ 1.35 1.36 // Reassign clazztype and recompute constructor. 1.37 clazztype = cdef.sym.type; 1.38 + boolean useVarargs = tree.varargsElement != null; 1.39 Symbol sym = rs.resolveConstructor( 1.40 tree.pos(), localEnv, clazztype, argtypes, 1.41 - typeargtypes, true, tree.varargsElement != null); 1.42 + typeargtypes, true, useVarargs); 1.43 Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous()); 1.44 tree.constructor = sym; 1.45 if (tree.constructor.kind > ERRONEOUS) { 1.46 @@ -1794,7 +1799,7 @@ 1.47 tree.args, 1.48 argtypes, 1.49 typeargtypes, 1.50 - localEnv.info.varArgs); 1.51 + useVarargs); 1.52 } 1.53 } 1.54
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/varargs/7043922/T7043922.java Mon May 16 09:38:04 2011 +0100 2.3 @@ -0,0 +1,189 @@ 2.4 +/* 2.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 7043922 2.30 + * @summary Regression: internal compiler error for nested anonymous inner class featuring varargs constructor 2.31 + */ 2.32 + 2.33 +import com.sun.source.util.JavacTask; 2.34 +import com.sun.tools.javac.api.JavacTool; 2.35 +import com.sun.tools.javac.util.List; 2.36 + 2.37 +import java.net.URI; 2.38 +import java.util.Arrays; 2.39 +import java.util.Locale; 2.40 +import javax.tools.Diagnostic; 2.41 +import javax.tools.JavaCompiler; 2.42 +import javax.tools.JavaFileObject; 2.43 +import javax.tools.SimpleJavaFileObject; 2.44 +import javax.tools.StandardJavaFileManager; 2.45 +import javax.tools.ToolProvider; 2.46 + 2.47 +public class T7043922 { 2.48 + 2.49 + ClassKind[] classKinds; 2.50 + ConstructorKind[] constructorKinds; 2.51 + 2.52 + T7043922(ClassKind[] classKinds, ConstructorKind[] constructorKinds) { 2.53 + this.classKinds = classKinds; 2.54 + this.constructorKinds = constructorKinds; 2.55 + } 2.56 + 2.57 + void compileAndCheck() throws Exception { 2.58 + JavaSource source = new JavaSource(); 2.59 + ErrorChecker ec = new ErrorChecker(); 2.60 + JavacTask ct = (JavacTask)tool.getTask(null, fm, ec, 2.61 + null, null, Arrays.asList(source)); 2.62 + ct.analyze(); 2.63 + if (ec.errorFound) { 2.64 + throw new Error("invalid diagnostics for source:\n" + 2.65 + source.getCharContent(true) + 2.66 + "\nCompiler diagnostics:\n" + ec.printDiags()); 2.67 + } 2.68 + } 2.69 + 2.70 + class JavaSource extends SimpleJavaFileObject { 2.71 + 2.72 + static final String source_template = "#C0 A0 { #K0 }\n" + 2.73 + "#C1 A1 { #K1 }\n" + 2.74 + "#C2 A2 { #K2 }\n" + 2.75 + "class D {\n" + 2.76 + " void test() {\n" + 2.77 + " new A0(#V0) {\n" + 2.78 + " void test() {\n" + 2.79 + " new A1(#V1) {\n" + 2.80 + " void test() {\n" + 2.81 + " new A2(#V2) {};\n" + 2.82 + " }\n" + 2.83 + " };\n" + 2.84 + " }\n" + 2.85 + " };\n" + 2.86 + " }\n" + 2.87 + "}\n"; 2.88 + 2.89 + String source; 2.90 + 2.91 + public JavaSource() { 2.92 + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 2.93 + source = source_template; 2.94 + for (int i = 0; i < 3; i++) { 2.95 + source = source.replaceAll("#C" + i, classKinds[i].classKind). 2.96 + replaceAll("#K" + i, classKinds[i].getConstructor("A" + i, constructorKinds[i])). 2.97 + replaceAll("#V" + i, constructorKinds[i].constrArgs); 2.98 + } 2.99 + } 2.100 + 2.101 + @Override 2.102 + public CharSequence getCharContent(boolean ignoreEncodingErrors) { 2.103 + return source; 2.104 + } 2.105 + } 2.106 + 2.107 + /** global decls ***/ 2.108 + 2.109 + enum ConstructorKind { 2.110 + DEFAULT("", ""), 2.111 + FIXED_ARITY("String s", "\"\""), 2.112 + VARIABLE_ARITY("String... ss", "\"\",\"\""); 2.113 + 2.114 + String constrParam; 2.115 + String constrArgs; 2.116 + 2.117 + private ConstructorKind(String constrParam, String constrArgs) { 2.118 + this.constrParam = constrParam; 2.119 + this.constrArgs = constrArgs; 2.120 + } 2.121 + } 2.122 + 2.123 + enum ClassKind { 2.124 + ABSTRACT("abstract class"), 2.125 + CLASS("class"), 2.126 + INTERFACE("interface"); 2.127 + 2.128 + String classKind; 2.129 + 2.130 + private ClassKind(String classKind) { 2.131 + this.classKind = classKind; 2.132 + } 2.133 + 2.134 + boolean isConstructorOk(ConstructorKind ck) { 2.135 + return this != INTERFACE || 2.136 + ck == ConstructorKind.DEFAULT; 2.137 + } 2.138 + 2.139 + String getConstructor(String className, ConstructorKind ck) { 2.140 + return this == INTERFACE ? 2.141 + "" : 2.142 + (className + "(" + ck.constrParam + ") {}"); 2.143 + } 2.144 + } 2.145 + 2.146 + // Create a single file manager and JavaCompiler tool 2.147 + // and reuse them for each compile to save time. 2.148 + static final StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); 2.149 + static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 2.150 + 2.151 + public static void main(String... args) throws Exception { 2.152 + for (ClassKind classKind1 : ClassKind.values()) { 2.153 + for (ConstructorKind constrKind1 : ConstructorKind.values()) { 2.154 + if (!classKind1.isConstructorOk(constrKind1)) continue; 2.155 + for (ClassKind classKind2 : ClassKind.values()) { 2.156 + for (ConstructorKind constrKind2 : ConstructorKind.values()) { 2.157 + if (!classKind2.isConstructorOk(constrKind2)) continue; 2.158 + for (ClassKind classKind3 : ClassKind.values()) { 2.159 + for (ConstructorKind constrKind3 : ConstructorKind.values()) { 2.160 + if (!classKind3.isConstructorOk(constrKind3)) continue; 2.161 + new T7043922(new ClassKind[] { classKind1, classKind2, classKind3 }, 2.162 + new ConstructorKind[] { constrKind1, constrKind2, constrKind3 }).compileAndCheck(); 2.163 + } 2.164 + } 2.165 + } 2.166 + } 2.167 + } 2.168 + } 2.169 + } 2.170 + 2.171 + static class ErrorChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 2.172 + 2.173 + boolean errorFound; 2.174 + List<String> errDiags = List.nil(); 2.175 + 2.176 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 2.177 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 2.178 + errDiags = errDiags.append(diagnostic.getMessage(Locale.getDefault())); 2.179 + errorFound = true; 2.180 + } 2.181 + } 2.182 + 2.183 + String printDiags() { 2.184 + StringBuilder buf = new StringBuilder(); 2.185 + for (String s : errDiags) { 2.186 + buf.append(s); 2.187 + buf.append("\n"); 2.188 + } 2.189 + return buf.toString(); 2.190 + } 2.191 + } 2.192 +}