test/tools/javac/7003595/T7003595.java

Mon, 26 Oct 2015 13:23:30 -0700

author
asaha
date
Mon, 26 Oct 2015 13:23:30 -0700
changeset 2999
683b3e7e05a7
parent 0
959103a6100f
permissions
-rw-r--r--

Added tag jdk8u76-b00 for changeset 10ffafaf5340

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 */
aoqi@0 23
aoqi@0 24 /*
aoqi@0 25 * @test
aoqi@0 26 * @bug 7003595
aoqi@0 27 * @summary IncompatibleClassChangeError with unreferenced local class with subclass
aoqi@0 28 */
aoqi@0 29
aoqi@0 30 import com.sun.source.util.JavacTask;
aoqi@0 31 import com.sun.tools.classfile.Attribute;
aoqi@0 32 import com.sun.tools.classfile.ClassFile;
aoqi@0 33 import com.sun.tools.classfile.InnerClasses_attribute;
aoqi@0 34 import com.sun.tools.classfile.ConstantPool.*;
aoqi@0 35 import com.sun.tools.javac.api.JavacTool;
aoqi@0 36
aoqi@0 37 import java.io.File;
aoqi@0 38 import java.net.URI;
aoqi@0 39 import java.util.Arrays;
aoqi@0 40 import java.util.ArrayList;
aoqi@0 41 import javax.tools.JavaCompiler;
aoqi@0 42 import javax.tools.JavaFileObject;
aoqi@0 43 import javax.tools.SimpleJavaFileObject;
aoqi@0 44 import javax.tools.StandardJavaFileManager;
aoqi@0 45 import javax.tools.ToolProvider;
aoqi@0 46
aoqi@0 47
aoqi@0 48 public class T7003595 {
aoqi@0 49
aoqi@0 50 /** global decls ***/
aoqi@0 51
aoqi@0 52 // Create a single file manager and reuse it for each compile to save time.
aoqi@0 53 static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
aoqi@0 54
aoqi@0 55 //statistics
aoqi@0 56 static int checkCount = 0;
aoqi@0 57
aoqi@0 58 enum ClassKind {
aoqi@0 59 NESTED("static class #N { #B }", "$", true),
aoqi@0 60 INNER("class #N { #B }", "$", false),
aoqi@0 61 LOCAL_REF("void test() { class #N { #B }; new #N(); }", "$1", false),
aoqi@0 62 LOCAL_NOREF("void test() { class #N { #B }; }", "$1", false),
aoqi@0 63 ANON("void test() { new Object() { #B }; }", "$1", false),
aoqi@0 64 NONE("", "", false);
aoqi@0 65
aoqi@0 66 String memberInnerStr;
aoqi@0 67 String sep;
aoqi@0 68 boolean staticAllowed;
aoqi@0 69
aoqi@0 70 private ClassKind(String memberInnerStr, String sep, boolean staticAllowed) {
aoqi@0 71 this.memberInnerStr = memberInnerStr;
aoqi@0 72 this.sep = sep;
aoqi@0 73 this.staticAllowed = staticAllowed;
aoqi@0 74 }
aoqi@0 75
aoqi@0 76 String getSource(String className, String outerName, String nested) {
aoqi@0 77 return memberInnerStr.replaceAll("#O", outerName).
aoqi@0 78 replaceAll("#N", className).replaceAll("#B", nested);
aoqi@0 79 }
aoqi@0 80
aoqi@0 81 static String getClassfileName(String[] names, ClassKind[] outerKinds, int pos) {
aoqi@0 82 System.out.println(" pos = " + pos + " kind = " + outerKinds[pos] + " sep = " + outerKinds[pos].sep);
aoqi@0 83 String name = outerKinds[pos] != ANON ?
aoqi@0 84 names[pos] : "";
aoqi@0 85 if (pos == 0) {
aoqi@0 86 return "Test" + outerKinds[pos].sep + name;
aoqi@0 87 } else {
aoqi@0 88 String outerStr = getClassfileName(names, outerKinds, pos - 1);
aoqi@0 89 return outerStr + outerKinds[pos].sep + name;
aoqi@0 90 }
aoqi@0 91 }
aoqi@0 92
aoqi@0 93 boolean isAllowed(ClassKind nestedKind) {
aoqi@0 94 return nestedKind != NESTED ||
aoqi@0 95 staticAllowed;
aoqi@0 96 }
aoqi@0 97 }
aoqi@0 98
aoqi@0 99 enum LocalInnerClass {
aoqi@0 100 LOCAL_REF("class L {}; new L();", "Test$1L"),
aoqi@0 101 LOCAL_NOREF("class L {};", "Test$1L"),
aoqi@0 102 ANON("new Object() {};", "Test$1"),
aoqi@0 103 NONE("", "");
aoqi@0 104
aoqi@0 105 String localInnerStr;
aoqi@0 106 String canonicalInnerStr;
aoqi@0 107
aoqi@0 108 private LocalInnerClass(String localInnerStr, String canonicalInnerStr) {
aoqi@0 109 this.localInnerStr = localInnerStr;
aoqi@0 110 this.canonicalInnerStr = canonicalInnerStr;
aoqi@0 111 }
aoqi@0 112 }
aoqi@0 113
aoqi@0 114 public static void main(String... args) throws Exception {
aoqi@0 115 for (ClassKind ck1 : ClassKind.values()) {
aoqi@0 116 String cname1 = "C1";
aoqi@0 117 for (ClassKind ck2 : ClassKind.values()) {
aoqi@0 118 if (!ck1.isAllowed(ck2)) continue;
aoqi@0 119 String cname2 = "C2";
aoqi@0 120 for (ClassKind ck3 : ClassKind.values()) {
aoqi@0 121 if (!ck2.isAllowed(ck3)) continue;
aoqi@0 122 String cname3 = "C3";
aoqi@0 123 new T7003595(new ClassKind[] {ck1, ck2, ck3}, new String[] { cname1, cname2, cname3 }).compileAndCheck();
aoqi@0 124 }
aoqi@0 125 }
aoqi@0 126 }
aoqi@0 127
aoqi@0 128 System.out.println("Total checks made: " + checkCount);
aoqi@0 129 }
aoqi@0 130
aoqi@0 131 /** instance decls **/
aoqi@0 132
aoqi@0 133 ClassKind[] cks;
aoqi@0 134 String[] cnames;
aoqi@0 135
aoqi@0 136 T7003595(ClassKind[] cks, String[] cnames) {
aoqi@0 137 this.cks = cks;
aoqi@0 138 this.cnames = cnames;
aoqi@0 139 }
aoqi@0 140
aoqi@0 141 void compileAndCheck() throws Exception {
aoqi@0 142 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
aoqi@0 143 JavaSource source = new JavaSource();
aoqi@0 144 JavacTask ct = (JavacTask)tool.getTask(null, fm, null,
aoqi@0 145 null, null, Arrays.asList(source));
aoqi@0 146 ct.call();
aoqi@0 147 verifyBytecode(source);
aoqi@0 148 }
aoqi@0 149
aoqi@0 150 void verifyBytecode(JavaSource source) {
aoqi@0 151 for (int i = 0; i < 3 ; i ++) {
aoqi@0 152 if (cks[i] == ClassKind.NONE) break;
aoqi@0 153 checkCount++;
aoqi@0 154 String filename = cks[i].getClassfileName(cnames, cks, i);
aoqi@0 155 File compiledTest = new File(filename + ".class");
aoqi@0 156 try {
aoqi@0 157 ClassFile cf = ClassFile.read(compiledTest);
aoqi@0 158 if (cf == null) {
aoqi@0 159 throw new Error("Classfile not found: " + filename);
aoqi@0 160 }
aoqi@0 161
aoqi@0 162 InnerClasses_attribute innerClasses = (InnerClasses_attribute)cf.getAttribute(Attribute.InnerClasses);
aoqi@0 163
aoqi@0 164 ArrayList<String> foundInnerSig = new ArrayList<>();
aoqi@0 165 if (innerClasses != null) {
aoqi@0 166 for (InnerClasses_attribute.Info info : innerClasses.classes) {
aoqi@0 167 String foundSig = info.getInnerClassInfo(cf.constant_pool).getName();
aoqi@0 168 foundInnerSig.add(foundSig);
aoqi@0 169 }
aoqi@0 170 }
aoqi@0 171
aoqi@0 172 ArrayList<String> expectedInnerSig = new ArrayList<>();
aoqi@0 173 //add inner class (if any)
aoqi@0 174 if (i < 2 && cks[i + 1] != ClassKind.NONE) {
aoqi@0 175 expectedInnerSig.add(cks[i + 1].getClassfileName(cnames, cks, i + 1));
aoqi@0 176 }
aoqi@0 177 //add inner classes
aoqi@0 178 for (int j = 0 ; j != i + 1 && j < 3; j++) {
aoqi@0 179 expectedInnerSig.add(cks[j].getClassfileName(cnames, cks, j));
aoqi@0 180 }
aoqi@0 181
aoqi@0 182 if (expectedInnerSig.size() != foundInnerSig.size()) {
aoqi@0 183 throw new Error("InnerClasses attribute for " + cnames[i] + " has wrong size\n" +
aoqi@0 184 "expected " + expectedInnerSig.size() + "\n" +
aoqi@0 185 "found " + innerClasses.number_of_classes + "\n" +
aoqi@0 186 source);
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 for (String foundSig : foundInnerSig) {
aoqi@0 190 if (!expectedInnerSig.contains(foundSig)) {
aoqi@0 191 throw new Error("InnerClasses attribute for " + cnames[i] + " has unexpected signature: " +
aoqi@0 192 foundSig + "\n" + source + "\n" + expectedInnerSig);
aoqi@0 193 }
aoqi@0 194 }
aoqi@0 195
aoqi@0 196 for (String expectedSig : expectedInnerSig) {
aoqi@0 197 if (!foundInnerSig.contains(expectedSig)) {
aoqi@0 198 throw new Error("InnerClasses attribute for " + cnames[i] + " does not contain expected signature: " +
aoqi@0 199 expectedSig + "\n" + source);
aoqi@0 200 }
aoqi@0 201 }
aoqi@0 202 } catch (Exception e) {
aoqi@0 203 e.printStackTrace();
aoqi@0 204 throw new Error("error reading " + compiledTest +": " + e);
aoqi@0 205 }
aoqi@0 206 }
aoqi@0 207 }
aoqi@0 208
aoqi@0 209 class JavaSource extends SimpleJavaFileObject {
aoqi@0 210
aoqi@0 211 static final String source_template = "class Test { #C }";
aoqi@0 212
aoqi@0 213 String source;
aoqi@0 214
aoqi@0 215 public JavaSource() {
aoqi@0 216 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
aoqi@0 217 String c3 = cks[2].getSource(cnames[2], cnames[1], "");
aoqi@0 218 String c2 = cks[1].getSource(cnames[1], cnames[0], c3);
aoqi@0 219 String c1 = cks[0].getSource(cnames[0], "Test", c2);
aoqi@0 220 source = source_template.replace("#C", c1);
aoqi@0 221 }
aoqi@0 222
aoqi@0 223 @Override
aoqi@0 224 public String toString() {
aoqi@0 225 return source;
aoqi@0 226 }
aoqi@0 227
aoqi@0 228 @Override
aoqi@0 229 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
aoqi@0 230 return source;
aoqi@0 231 }
aoqi@0 232 }
aoqi@0 233 }

mercurial