1 /* 2 * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 7043922 27 * @summary Regression: internal compiler error for nested anonymous inner class featuring varargs constructor 28 * @modules jdk.compiler/com.sun.tools.javac.api 29 * jdk.compiler/com.sun.tools.javac.file 30 * jdk.compiler/com.sun.tools.javac.util 31 */ 32 33 import com.sun.source.util.JavacTask; 34 import com.sun.tools.javac.api.JavacTool; 35 import com.sun.tools.javac.util.List; 36 37 import java.net.URI; 38 import java.util.Arrays; 39 import java.util.Locale; 40 import javax.tools.Diagnostic; 41 import javax.tools.JavaCompiler; 42 import javax.tools.JavaFileObject; 43 import javax.tools.SimpleJavaFileObject; 44 import javax.tools.StandardJavaFileManager; 45 import javax.tools.ToolProvider; 46 47 public class T7043922 { 48 49 ClassKind[] classKinds; 50 ConstructorKind[] constructorKinds; 51 52 T7043922(ClassKind[] classKinds, ConstructorKind[] constructorKinds) { 53 this.classKinds = classKinds; 54 this.constructorKinds = constructorKinds; 55 } 56 57 void compileAndCheck() throws Exception { 58 JavaSource source = new JavaSource(); 59 ErrorChecker ec = new ErrorChecker(); 60 JavacTask ct = (JavacTask)tool.getTask(null, fm, ec, 61 null, null, Arrays.asList(source)); 62 ct.analyze(); 63 if (ec.errorFound) { 64 throw new Error("invalid diagnostics for source:\n" + 65 source.getCharContent(true) + 66 "\nCompiler diagnostics:\n" + ec.printDiags()); 67 } 68 } 69 70 class JavaSource extends SimpleJavaFileObject { 71 72 static final String source_template = "#C0 A0 { #K0 }\n" + 73 "#C1 A1 { #K1 }\n" + 74 "#C2 A2 { #K2 }\n" + 75 "class D {\n" + 76 " void test() {\n" + 77 " new A0(#V0) {\n" + 78 " void test() {\n" + 79 " new A1(#V1) {\n" + 80 " void test() {\n" + 81 " new A2(#V2) {};\n" + 82 " }\n" + 83 " };\n" + 84 " }\n" + 85 " };\n" + 86 " }\n" + 87 "}\n"; 88 89 String source; 90 91 public JavaSource() { 92 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 93 source = source_template; 94 for (int i = 0; i < 3; i++) { 95 source = source.replaceAll("#C" + i, classKinds[i].classKind). 96 replaceAll("#K" + i, classKinds[i].getConstructor("A" + i, constructorKinds[i])). 97 replaceAll("#V" + i, constructorKinds[i].constrArgs); 98 } 99 } 100 101 @Override 102 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 103 return source; 104 } 105 } 106 107 /** global decls ***/ 108 109 enum ConstructorKind { 110 DEFAULT("", ""), 111 FIXED_ARITY("String s", "\"\""), 112 VARIABLE_ARITY("String... ss", "\"\",\"\""); 113 114 String constrParam; 115 String constrArgs; 116 117 private ConstructorKind(String constrParam, String constrArgs) { 118 this.constrParam = constrParam; 119 this.constrArgs = constrArgs; 120 } 121 } 122 123 enum ClassKind { 124 ABSTRACT("abstract class"), 125 CLASS("class"), 126 INTERFACE("interface"); 127 128 String classKind; 129 130 private ClassKind(String classKind) { 131 this.classKind = classKind; 132 } 133 134 boolean isConstructorOk(ConstructorKind ck) { 135 return this != INTERFACE || 136 ck == ConstructorKind.DEFAULT; 137 } 138 139 String getConstructor(String className, ConstructorKind ck) { 140 return this == INTERFACE ? 141 "" : 142 (className + "(" + ck.constrParam + ") {}"); 143 } 144 } 145 146 // Create a single file manager and JavaCompiler tool 147 // and reuse them for each compile to save time. 148 static final StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); 149 static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 150 151 public static void main(String... args) throws Exception { 152 try { 153 for (ClassKind classKind1 : ClassKind.values()) { 154 for (ConstructorKind constrKind1 : ConstructorKind.values()) { 155 if (!classKind1.isConstructorOk(constrKind1)) continue; 156 for (ClassKind classKind2 : ClassKind.values()) { 157 for (ConstructorKind constrKind2 : ConstructorKind.values()) { 158 if (!classKind2.isConstructorOk(constrKind2)) continue; 159 for (ClassKind classKind3 : ClassKind.values()) { 160 for (ConstructorKind constrKind3 : ConstructorKind.values()) { 161 if (!classKind3.isConstructorOk(constrKind3)) continue; 162 new T7043922(new ClassKind[] { classKind1, classKind2, classKind3 }, 163 new ConstructorKind[] { constrKind1, constrKind2, constrKind3 }).compileAndCheck(); 164 } 165 } 166 } 167 } 168 } 169 } 170 } finally { 171 fm.close(); 172 } 173 } 174 175 static class ErrorChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 176 177 boolean errorFound; 178 List<String> errDiags = List.nil(); 179 180 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 181 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 182 errDiags = errDiags.append(diagnostic.getMessage(Locale.getDefault())); 183 errorFound = true; 184 } 185 } 186 187 String printDiags() { 188 StringBuilder buf = new StringBuilder(); 189 for (String s : errDiags) { 190 buf.append(s); 191 buf.append("\n"); 192 } 193 return buf.toString(); 194 } 195 } 196 }