Mon, 17 Oct 2011 12:57:36 +0100
7093325: Redundant entry in bytecode exception table
Summary: Inlining of finalizers does not update gaps list accordingly
Reviewed-by: jjg
jjg@898 | 1 | /* |
jjg@898 | 2 | * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. |
jjg@898 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
jjg@898 | 4 | * |
jjg@898 | 5 | * This code is free software; you can redistribute it and/or modify it |
jjg@898 | 6 | * under the terms of the GNU General Public License version 2 only, as |
jjg@898 | 7 | * published by the Free Software Foundation. |
jjg@898 | 8 | * |
jjg@898 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
jjg@898 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
jjg@898 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
jjg@898 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
jjg@898 | 13 | * accompanied this code). |
jjg@898 | 14 | * |
jjg@898 | 15 | * You should have received a copy of the GNU General Public License version |
jjg@898 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
jjg@898 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
jjg@898 | 18 | * |
jjg@898 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
jjg@898 | 20 | * or visit www.oracle.com if you need additional information or have any |
jjg@898 | 21 | * questions. |
jjg@898 | 22 | */ |
jjg@898 | 23 | |
jjg@898 | 24 | |
jjg@898 | 25 | /* |
jjg@898 | 26 | * @test |
jjg@898 | 27 | * @bug 7022337 |
jjg@898 | 28 | * @summary repeated warnings about bootclasspath not set |
jjg@898 | 29 | * @library ../lib |
jjg@898 | 30 | * @build JavacTestingAbstractProcessor TestWarnErrorCount |
jjg@898 | 31 | * @run main TestWarnErrorCount |
jjg@898 | 32 | */ |
jjg@898 | 33 | |
jjg@898 | 34 | import java.io.*; |
jjg@898 | 35 | import java.util.*; |
jjg@898 | 36 | import javax.annotation.processing.*; |
jjg@898 | 37 | import javax.lang.model.element.*; |
jjg@898 | 38 | import javax.tools.*; |
jjg@898 | 39 | |
jjg@898 | 40 | @SupportedOptions({"errKind", "msgrWarnKind", "javaWarnKind"}) |
jjg@898 | 41 | public class TestWarnErrorCount extends JavacTestingAbstractProcessor { |
jjg@898 | 42 | public static void main(String... args) throws Exception { |
jjg@898 | 43 | new TestWarnErrorCount().run(args); |
jjg@898 | 44 | } |
jjg@898 | 45 | |
jjg@898 | 46 | final int MAX_GEN = 10; |
jjg@898 | 47 | final int ERROR_ROUND = MAX_GEN / 2; // when to generate error |
jjg@898 | 48 | |
jjg@898 | 49 | /** |
jjg@898 | 50 | * Type of errors to generate in test case. |
jjg@898 | 51 | */ |
jjg@898 | 52 | enum ErrorKind { |
jjg@898 | 53 | /** No errors. */ |
jjg@898 | 54 | NONE, |
jjg@898 | 55 | /** Source code errors. */ |
jjg@898 | 56 | JAVA, |
jjg@898 | 57 | /** Errors reported to Messager. */ |
jjg@898 | 58 | MESSAGER, |
jjg@898 | 59 | /** Error as a result of using -Werror. */ |
jjg@898 | 60 | WERROR, |
jjg@898 | 61 | } |
jjg@898 | 62 | |
jjg@898 | 63 | /** |
jjg@898 | 64 | * Frequency of warnings in test case. |
jjg@898 | 65 | */ |
jjg@898 | 66 | enum WarnKind { |
jjg@898 | 67 | /** No warnings. */ |
jjg@898 | 68 | NONE { |
jjg@898 | 69 | boolean warn(int round) { return false; } |
jjg@898 | 70 | int count(int start, int end) { return 0; } |
jjg@898 | 71 | }, |
jjg@898 | 72 | /** Generate a warning if round count is a multiple of 2. */ |
jjg@898 | 73 | EVERY_TWO { |
jjg@898 | 74 | boolean warn(int round) { return (round % 2) == 0; } |
jjg@898 | 75 | int count(int start, int end) { return (end / 2) - ((start - 1)/ 2); } |
jjg@898 | 76 | }, |
jjg@898 | 77 | /** Generate a warning if round count is a multiple of 3. */ |
jjg@898 | 78 | EVERY_THREE { |
jjg@898 | 79 | boolean warn(int round) { return (round % 3) == 0; } |
jjg@898 | 80 | int count(int start, int end) { return (end / 3) - ((start - 1)/ 3); } |
jjg@898 | 81 | }, |
jjg@898 | 82 | /** Generate a warning every round. */ |
jjg@898 | 83 | ALL { |
jjg@898 | 84 | boolean warn(int round) { return true; } |
jjg@898 | 85 | int count(int start, int end) { return (end - start + 1); } |
jjg@898 | 86 | }; |
jjg@898 | 87 | |
jjg@898 | 88 | /** whether to generate a warning in round 'round'. */ |
jjg@898 | 89 | abstract boolean warn(int round); |
jjg@898 | 90 | |
jjg@898 | 91 | /** number of warnings generated in a range of rounds, inclusive. */ |
jjg@898 | 92 | abstract int count(int start, int end); |
jjg@898 | 93 | } |
jjg@898 | 94 | |
jjg@898 | 95 | |
jjg@898 | 96 | /** |
jjg@898 | 97 | * Run test. |
jjg@898 | 98 | * @param args provide ability to specify particular test cases for debugging. |
jjg@898 | 99 | */ |
jjg@898 | 100 | void run(String... args) throws Exception { |
jjg@898 | 101 | for (String arg: args) { |
jjg@898 | 102 | if (arg.matches("[0-9]+")) { |
jjg@898 | 103 | if (testCases == null) |
jjg@898 | 104 | testCases = new HashSet<Integer>(); |
jjg@898 | 105 | testCases.add(Integer.valueOf(arg)); |
jjg@898 | 106 | } else if (arg.equals("-stopOnError")) { |
jjg@898 | 107 | stopOnError = true; |
jjg@898 | 108 | } else |
jjg@898 | 109 | throw new IllegalArgumentException(arg); |
jjg@898 | 110 | } |
jjg@898 | 111 | |
jjg@898 | 112 | run (); |
jjg@898 | 113 | |
jjg@898 | 114 | if (errors > 0) |
jjg@898 | 115 | throw new Exception(errors + " errors found"); |
jjg@898 | 116 | } |
jjg@898 | 117 | |
jjg@898 | 118 | /** |
jjg@898 | 119 | * Run test. |
jjg@898 | 120 | */ |
jjg@898 | 121 | void run() throws Exception { |
jjg@898 | 122 | for (ErrorKind ek: ErrorKind.values()) { |
jjg@898 | 123 | for (WarnKind mwk: WarnKind.values()) { |
jjg@898 | 124 | for (WarnKind jwk: WarnKind.values()) { |
jjg@898 | 125 | test(ek, mwk, jwk); |
jjg@898 | 126 | if (stopOnError && errors > 0) |
jjg@898 | 127 | throw new Exception(errors + " errors found"); |
jjg@898 | 128 | } |
jjg@898 | 129 | } |
jjg@898 | 130 | } |
jjg@898 | 131 | } |
jjg@898 | 132 | |
jjg@898 | 133 | boolean stopOnError; |
jjg@898 | 134 | Set<Integer> testCases; |
jjg@898 | 135 | int testNum = 0; |
jjg@898 | 136 | |
jjg@898 | 137 | /** |
jjg@898 | 138 | * Run a test case. |
jjg@898 | 139 | * @param ek The type of errors to generate |
jjg@898 | 140 | * @param mwk The frequency of Messager warnings to generate |
jjg@898 | 141 | * @param jwk The frequency of Java warnings to generate |
jjg@898 | 142 | */ |
jjg@898 | 143 | void test(ErrorKind ek, WarnKind mwk, WarnKind jwk) { |
jjg@898 | 144 | testNum++; |
jjg@898 | 145 | |
jjg@898 | 146 | if (testCases != null && !testCases.contains(testNum)) |
jjg@898 | 147 | return; |
jjg@898 | 148 | |
jjg@898 | 149 | System.err.println("Test " + testNum + ": ek:" + ek + " mwk:" + mwk + " jwk:" + jwk); |
jjg@898 | 150 | |
jjg@898 | 151 | File testDir = new File("test" + testNum); |
jjg@898 | 152 | testDir.mkdirs(); |
jjg@898 | 153 | |
jjg@898 | 154 | String myName = TestWarnErrorCount.class.getSimpleName(); |
jjg@898 | 155 | File testSrc = new File(System.getProperty("test.src")); |
jjg@898 | 156 | File file = new File(testSrc, myName + ".java"); |
jjg@898 | 157 | |
jjg@898 | 158 | List<String> args = new ArrayList<String>(); |
jjg@898 | 159 | args.addAll(Arrays.asList( |
jjg@898 | 160 | "-XDrawDiagnostics", |
jjg@898 | 161 | "-d", testDir.getPath(), |
jjg@898 | 162 | "-processor", myName, |
jjg@898 | 163 | // "-XprintRounds", |
mcimadamore@908 | 164 | "-Xlint:all,-path", |
jjg@898 | 165 | "-AerrKind=" + ek, |
jjg@898 | 166 | "-AmsgrWarnKind=" + mwk, |
jjg@898 | 167 | "-AjavaWarnKind=" + jwk)); |
jjg@898 | 168 | if (ek == ErrorKind.WERROR) |
jjg@898 | 169 | args.add("-Werror"); |
jjg@898 | 170 | args.add(file.getPath()); |
jjg@898 | 171 | |
jjg@898 | 172 | String out = compile(args.toArray(new String[args.size()])); |
jjg@898 | 173 | |
jjg@898 | 174 | int errsFound = 0; |
jjg@898 | 175 | int errsReported = 0; |
jjg@898 | 176 | int warnsFound = 0; |
jjg@898 | 177 | int warnsReported = 0; |
jjg@898 | 178 | |
jjg@898 | 179 | // Scan the output looking for messages of interest. |
jjg@898 | 180 | |
jjg@898 | 181 | for (String line: out.split("[\r\n]+")) { |
jjg@898 | 182 | if (line.contains("compiler.err.")) { |
jjg@898 | 183 | errsFound++; |
jjg@898 | 184 | } else if (line.contains("compiler.warn.")) { |
jjg@898 | 185 | warnsFound++; |
jjg@898 | 186 | } else if (line.matches("[0-9]+ error(?:s?)")) { |
jjg@898 | 187 | errsReported = Integer.valueOf(line.substring(0, line.indexOf("error")).trim()); |
jjg@898 | 188 | } else if (line.matches("[0-9]+ warning(?:s?)")) { |
jjg@898 | 189 | warnsReported = Integer.valueOf(line.substring(0, line.indexOf("warning")).trim()); |
jjg@898 | 190 | } |
jjg@898 | 191 | } |
jjg@898 | 192 | |
jjg@898 | 193 | // Compute the expected number of errors and warnings, based on |
jjg@898 | 194 | // the test case parameters. |
jjg@898 | 195 | // This is highly specific to the annotation processor below, and to |
jjg@898 | 196 | // the files it generates. |
jjg@898 | 197 | // Generally, the rules are: |
jjg@898 | 198 | // -- errors stop annotation processing, allowing for one extra "last round" |
jjg@898 | 199 | // -- messager warnings are immediate |
jjg@898 | 200 | // -- javac warnings are not shown before the final compilation |
jjg@898 | 201 | // (FIXME? -Werror does not stop processing for java warnings) |
jjg@898 | 202 | int errsExpected; |
jjg@898 | 203 | int msgrWarnsExpected; |
jjg@898 | 204 | int javaWarnsExpected; |
jjg@898 | 205 | switch (ek) { |
jjg@898 | 206 | case NONE: |
jjg@898 | 207 | errsExpected = 0; |
jjg@898 | 208 | msgrWarnsExpected = mwk.count(1, 1 + MAX_GEN + 1); |
jjg@898 | 209 | javaWarnsExpected = jwk.count(2, 1 + MAX_GEN); |
jjg@898 | 210 | break; |
jjg@898 | 211 | case MESSAGER: |
jjg@898 | 212 | errsExpected = 1; |
jjg@898 | 213 | msgrWarnsExpected = mwk.count(1, ERROR_ROUND + 1); |
jjg@898 | 214 | javaWarnsExpected = 0; |
jjg@898 | 215 | break; |
jjg@898 | 216 | case JAVA: |
jjg@898 | 217 | errsExpected = 2; |
jjg@898 | 218 | msgrWarnsExpected = mwk.count(1, ERROR_ROUND + 1); |
jjg@898 | 219 | javaWarnsExpected = 0; |
jjg@898 | 220 | break; |
jjg@898 | 221 | case WERROR: |
jjg@898 | 222 | errsExpected = (mwk != WarnKind.NONE || jwk != WarnKind.NONE) ? 1 : 0; |
jjg@898 | 223 | switch (mwk) { |
jjg@898 | 224 | case NONE: |
jjg@898 | 225 | msgrWarnsExpected = 0; |
jjg@898 | 226 | javaWarnsExpected = (jwk == WarnKind.NONE) |
jjg@898 | 227 | ? 0 |
jjg@898 | 228 | : 1; // this is surprising: javac only reports warning in first file |
jjg@898 | 229 | break; |
jjg@898 | 230 | case EVERY_TWO: |
jjg@898 | 231 | msgrWarnsExpected = mwk.count(1, 2 + 1); |
jjg@898 | 232 | javaWarnsExpected = 0; |
jjg@898 | 233 | break; |
jjg@898 | 234 | case EVERY_THREE: |
jjg@898 | 235 | msgrWarnsExpected = mwk.count(1, 3 + 1); |
jjg@898 | 236 | javaWarnsExpected = 0; |
jjg@898 | 237 | break; |
jjg@898 | 238 | case ALL: |
jjg@898 | 239 | msgrWarnsExpected = mwk.count(1, 1 + 1); |
jjg@898 | 240 | javaWarnsExpected = 0; |
jjg@898 | 241 | break; |
jjg@898 | 242 | default: |
jjg@898 | 243 | throw new IllegalStateException(); |
jjg@898 | 244 | } |
jjg@898 | 245 | break; |
jjg@898 | 246 | default: |
jjg@898 | 247 | throw new IllegalStateException(); |
jjg@898 | 248 | } |
jjg@898 | 249 | |
jjg@898 | 250 | int warnsExpected = msgrWarnsExpected + javaWarnsExpected; |
jjg@898 | 251 | System.err.println("mwk: " + msgrWarnsExpected |
jjg@898 | 252 | + ", jwk: " + javaWarnsExpected |
jjg@898 | 253 | + ", total: " + warnsExpected); |
jjg@898 | 254 | |
jjg@898 | 255 | boolean ok; |
jjg@898 | 256 | ok = checkEqual("errors", "reported", errsFound, errsReported); |
jjg@898 | 257 | ok &= checkEqual("errors", "expected", errsFound, errsExpected); |
jjg@898 | 258 | ok &= checkEqual("warnings", "reported", warnsFound, warnsReported); |
jjg@898 | 259 | ok &= checkEqual("warnings", "expected", warnsFound, warnsExpected); |
jjg@898 | 260 | if (ok) |
jjg@898 | 261 | System.err.println("OK"); |
jjg@898 | 262 | |
jjg@898 | 263 | System.err.println(); |
jjg@898 | 264 | } |
jjg@898 | 265 | |
jjg@898 | 266 | String compile(String... args) { |
jjg@898 | 267 | StringWriter sw = new StringWriter(); |
jjg@898 | 268 | PrintWriter pw = new PrintWriter(sw); |
jjg@898 | 269 | int rc = com.sun.tools.javac.Main.compile(args, pw); |
jjg@898 | 270 | pw.close(); |
jjg@898 | 271 | String out = sw.toString(); |
jjg@898 | 272 | if (!out.isEmpty()) |
jjg@898 | 273 | System.err.println(out); |
jjg@898 | 274 | if (rc != 0) |
jjg@898 | 275 | System.err.println("compilation failed: rc=" + rc); |
jjg@898 | 276 | return out; |
jjg@898 | 277 | } |
jjg@898 | 278 | |
jjg@898 | 279 | boolean checkEqual(String l1, String l2, int i1, int i2) { |
jjg@898 | 280 | if (i1 != i2) |
jjg@898 | 281 | error("number of " + l1 + " found, " + i1 + ", does not match number " + l2 + ", " + i2); |
jjg@898 | 282 | return (i1 == i2); |
jjg@898 | 283 | } |
jjg@898 | 284 | |
jjg@898 | 285 | void error(String msg) { |
jjg@898 | 286 | System.err.println("Error: " + msg); |
jjg@898 | 287 | errors++; |
jjg@898 | 288 | } |
jjg@898 | 289 | |
jjg@898 | 290 | int errors = 0; |
jjg@898 | 291 | |
jjg@898 | 292 | // ----- Annotation processor ----- |
jjg@898 | 293 | |
jjg@898 | 294 | int round = 0; |
jjg@898 | 295 | |
jjg@898 | 296 | @Override |
jjg@898 | 297 | public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
jjg@898 | 298 | round++; |
jjg@898 | 299 | |
jjg@898 | 300 | ErrorKind ek = ErrorKind.valueOf(options.get("errKind")); |
jjg@898 | 301 | WarnKind mwk = WarnKind.valueOf(options.get("msgrWarnKind")); |
jjg@898 | 302 | WarnKind jwk = WarnKind.valueOf(options.get("javaWarnKind")); |
jjg@898 | 303 | messager.printMessage(Diagnostic.Kind.NOTE, |
jjg@898 | 304 | "Round " + round |
jjg@898 | 305 | + " " + roundEnv.getRootElements() |
jjg@898 | 306 | + ", last round: " + roundEnv.processingOver()); |
jjg@898 | 307 | messager.printMessage(Diagnostic.Kind.NOTE, |
jjg@898 | 308 | "ek: " + ek + ", mwk: " + mwk + ", jwk: " + jwk); |
jjg@898 | 309 | |
jjg@898 | 310 | if (round <= MAX_GEN && !roundEnv.processingOver()) |
jjg@898 | 311 | generate("Gen" + round, |
jjg@898 | 312 | (ek == ErrorKind.JAVA) && (round == ERROR_ROUND), |
jjg@898 | 313 | jwk.warn(round)); |
jjg@898 | 314 | |
jjg@898 | 315 | if (mwk.warn(round)) |
jjg@898 | 316 | messager.printMessage(Diagnostic.Kind.WARNING, "round " + round); |
jjg@898 | 317 | |
jjg@898 | 318 | if ((ek == ErrorKind.MESSAGER) && (round == ERROR_ROUND)) |
jjg@898 | 319 | messager.printMessage(Diagnostic.Kind.ERROR, "round " + round); |
jjg@898 | 320 | |
jjg@898 | 321 | return true; |
jjg@898 | 322 | } |
jjg@898 | 323 | |
jjg@898 | 324 | void generate(String name, boolean error, boolean warn) { |
jjg@898 | 325 | try { |
jjg@898 | 326 | JavaFileObject fo = filer.createSourceFile(name); |
jjg@898 | 327 | Writer out = fo.openWriter(); |
jjg@898 | 328 | try { |
jjg@898 | 329 | out.write("class " + name + " {\n" |
jjg@898 | 330 | + (warn ? " int i = (int) 0;\n" : "") |
jjg@898 | 331 | + (error ? " ERROR\n" : "") |
jjg@898 | 332 | + "}\n"); |
jjg@898 | 333 | } finally { |
jjg@898 | 334 | out.close(); |
jjg@898 | 335 | } |
jjg@898 | 336 | } catch (IOException e) { |
jjg@898 | 337 | throw new Error(e); |
jjg@898 | 338 | } |
jjg@898 | 339 | } |
jjg@898 | 340 | } |