Mercurial > hg > openjdk > bsd-port > langtools
changeset 2121:85832379d0f9
Merge
author | asaha |
---|---|
date | Tue, 10 Mar 2015 15:49:28 -0700 |
parents | 7c8b319a6905 (diff) 185113eafdbf (current diff) |
children | 242015274be2 |
files | |
diffstat | 25 files changed, 1172 insertions(+), 64 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Mar 10 15:41:40 2015 -0700 +++ b/.hgtags Tue Mar 10 15:49:28 2015 -0700 @@ -576,3 +576,17 @@ e0d3d80136d7cd11fd26f22fead1f78068fdddaf jdk7u79-b11 a5f2b51a4ea77cd5471d03501a460c80b375379a jdk7u79-b12 525562d90c3c06ddc9ef6c266db2d2aa8177b7e0 jdk7u79-b13 +772aad4e9681828b8ee193b9ed971cbfe6c7f347 jdk7u80-b00 +6c307a0b7a94e002d8a2532ffd8146d6c53f42d3 jdk7u80-b01 +5bd6f3adf690dc2de8881b6f9f48336db4af7865 jdk7u80-b02 +bcbd241df6cd0a643480c8de183c541a662dd506 jdk7u80-b03 +04b56f4312b62d8bdf4eb1159132de8437994d34 jdk7u80-b04 +f40fb76025c798cab4fb0e1966be1bceb8234527 jdk7u80-b05 +335ee524dc68a42863f3fa3f081b781586e7ba2d jdk7u80-b06 +6f7b359c4e9f82cbd399edc93c3275c3e668d2ea jdk7u80-b07 +e6db2a97b3696fb5e7786b23f77af346a935a370 jdk7u80-b08 +88b7f1ad17d20eace30d0ab83d4e7413c0c863ff jdk7u80-b09 +55f4bb77c71c8e0b9be2ac6484c7a3838203d53a jdk7u80-b10 +ae5ecf167fb7d70f98aa117ea6a053307db98b14 jdk7u80-b11 +c084fb3e386393774886645aee8ef57b22854c08 jdk7u80-b12 +e6845c405f95b6336e000f054f87a964a33927d9 jdk7u80-b13
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 10 15:41:40 2015 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 10 15:49:28 2015 -0700 @@ -2400,9 +2400,9 @@ } }); for (Scope.Entry e = a.annotationType.type.tsym.members().elems; - e != null; - e = e.sibling) - if (e.sym.kind == MTH) + e != null; + e = e.sibling) + if (e.sym.kind == MTH && e.sym.name != names.clinit) members.add((MethodSymbol) e.sym); // count them off as they're annotated
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Tue Mar 10 15:41:40 2015 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Tue Mar 10 15:49:28 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -223,6 +223,12 @@ meth.name, bridgeType, origin); + /* once JDK-6996415 is solved it should be checked if this approach can + * be applied to method addOverrideBridgesIfNeeded + */ + bridge.params = createBridgeParams(impl, bridge, bridgeType); + bridge.attributes_field = impl.attributes_field; + if (!hypothetical) { JCMethodDecl md = make.MethodDef(bridge, null); @@ -257,6 +263,26 @@ overridden.put(bridge, meth); } + private List<VarSymbol> createBridgeParams(MethodSymbol impl, MethodSymbol bridge, + Type bridgeType) { + List<VarSymbol> bridgeParams = null; + if (impl.params != null) { + bridgeParams = List.nil(); + List<VarSymbol> implParams = impl.params; + Type.MethodType mType = (Type.MethodType)bridgeType; + List<Type> argTypes = mType.argtypes; + while (implParams.nonEmpty() && argTypes.nonEmpty()) { + VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER, + implParams.head.name, argTypes.head, bridge); + param.attributes_field = implParams.head.attributes_field; + bridgeParams = bridgeParams.append(param); + implParams = implParams.tail; + argTypes = argTypes.tail; + } + } + return bridgeParams; + } + /** Add bridge if given symbol is a non-private, non-static member * of the given class, which is either defined in the class or non-final * inherited, and one of the two following conditions holds:
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Mar 10 15:41:40 2015 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Mar 10 15:49:28 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -1541,15 +1541,17 @@ // The method wasn't found: emit a warning and recover JavaFileObject prevSource = log.useSource(requestingOwner.classfile); try { - if (failure == null) { - log.warning("annotation.method.not.found", - container, - name); - } else { - log.warning("annotation.method.not.found.reason", - container, - name, - failure.getDetailValue());//diagnostic, if present + if (lintClassfile) { + if (failure == null) { + log.warning("annotation.method.not.found", + container, + name); + } else { + log.warning("annotation.method.not.found.reason", + container, + name, + failure.getDetailValue()); //diagnostic, if present + } } } finally { log.useSource(prevSource);
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Tue Mar 10 15:41:40 2015 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Tue Mar 10 15:49:28 2015 -0700 @@ -1012,25 +1012,29 @@ if (code.varBufferSize > 0) { int alenIdx = writeAttr(names.LocalVariableTable); - databuf.appendChar(code.varBufferSize); + databuf.appendChar(code.getLVTSize()); for (int i=0; i<code.varBufferSize; i++) { Code.LocalVar var = code.varBuffer[i]; - - // write variable info - Assert.check(var.start_pc >= 0 - && var.start_pc <= code.cp); - databuf.appendChar(var.start_pc); - Assert.check(var.length >= 0 - && (var.start_pc + var.length) <= code.cp); - databuf.appendChar(var.length); - VarSymbol sym = var.sym; - databuf.appendChar(pool.put(sym.name)); - Type vartype = sym.erasure(types); - if (needsLocalVariableTypeEntry(sym.type)) - nGenericVars++; - databuf.appendChar(pool.put(typeSig(vartype))); - databuf.appendChar(var.reg); + for (Code.LocalVar.Range r: var.aliveRanges) { + // write variable info + if (!(r.start_pc >= 0 && r.start_pc <= code.cp)) { + throw new AssertionError(); + } + databuf.appendChar(r.start_pc); + if (!(r.length >= 0 && (r.start_pc + r.length) <= code.cp)) { + throw new AssertionError(); + } + databuf.appendChar(r.length); + VarSymbol sym = var.sym; + databuf.appendChar(pool.put(sym.name)); + Type vartype = sym.erasure(types); + databuf.appendChar(pool.put(typeSig(vartype))); + databuf.appendChar(var.reg); + if (needsLocalVariableTypeEntry(var.sym.type)) { + nGenericVars++; + } + } } endAttr(alenIdx); acount++; @@ -1046,13 +1050,15 @@ VarSymbol sym = var.sym; if (!needsLocalVariableTypeEntry(sym.type)) continue; - count++; - // write variable info - databuf.appendChar(var.start_pc); - databuf.appendChar(var.length); - databuf.appendChar(pool.put(sym.name)); - databuf.appendChar(pool.put(typeSig(sym.type))); - databuf.appendChar(var.reg); + for (Code.LocalVar.Range r : var.aliveRanges) { + // write variable info + databuf.appendChar(r.start_pc); + databuf.appendChar(r.length); + databuf.appendChar(pool.put(sym.name)); + databuf.appendChar(pool.put(typeSig(sym.type))); + databuf.appendChar(var.reg); + count++; + } } Assert.check(count == nGenericVars); endAttr(alenIdx);
--- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Tue Mar 10 15:41:40 2015 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Tue Mar 10 15:49:28 2015 -0700 @@ -1151,7 +1151,9 @@ public int entryPoint(State state) { int pc = curPc(); alive = true; - this.state = state.dup(); + State newState = state.dup(); + setDefined(newState.defined); + this.state = newState; Assert.check(state.stacksize <= max_stack); if (debugCode) System.err.println("entry point " + state); pendingStackMap = needStackMap; @@ -1164,7 +1166,9 @@ public int entryPoint(State state, Type pushed) { int pc = curPc(); alive = true; - this.state = state.dup(); + State newState = state.dup(); + setDefined(newState.defined); + this.state = newState; Assert.check(state.stacksize <= max_stack); this.state.push(pushed); if (debugCode) System.err.println("entry point " + state); @@ -1452,6 +1456,10 @@ chain.pc + 3 == target && target == cp && !fixedPc) { // If goto the next instruction, the jump is not needed: // compact the code. + if (varDebugInfo) { + adjustAliveRanges(cp, -3); + } + cp = cp - 3; target = target - 3; if (chain.next == null) { @@ -1736,8 +1744,7 @@ sym = sym.clone(sym.owner); sym.type = newtype; LocalVar newlv = lvar[i] = new LocalVar(sym); - // should the following be initialized to cp? - newlv.start_pc = lv.start_pc; + newlv.aliveRanges = lv.aliveRanges; } } } @@ -1825,18 +1832,118 @@ static class LocalVar { final VarSymbol sym; final char reg; - char start_pc = Character.MAX_VALUE; - char length = Character.MAX_VALUE; + + class Range { + char start_pc = Character.MAX_VALUE; + char length = Character.MAX_VALUE; + + Range() {} + + Range(char start) { + this.start_pc = start; + } + + Range(char start, char length) { + this.start_pc = start; + this.length = length; + } + + boolean closed() { + return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE; + } + + @Override + public String toString() { + int currentStartPC = start_pc; + int currentLength = length; + return "startpc = " + currentStartPC + " length " + currentLength; + } + } + + java.util.List<Range> aliveRanges = new java.util.ArrayList<Range>(); + LocalVar(VarSymbol v) { this.sym = v; this.reg = (char)v.adr; } + public LocalVar dup() { return new LocalVar(sym); } + + Range firstRange() { + return aliveRanges.isEmpty() ? null : aliveRanges.get(0); + } + + Range lastRange() { + return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); + } + + void removeLastRange() { + Range lastRange = lastRange(); + if (lastRange != null) { + aliveRanges.remove(lastRange); + } + } + + @Override public String toString() { - return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length); + if (aliveRanges == null) { + return "empty local var"; + } + StringBuilder sb = new StringBuilder().append(sym) + .append(" in register ").append((int)reg).append(" \n"); + for (Range r : aliveRanges) { + sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc))) + .append(" length=").append(Integer.toString(((int)r.length))) + .append("\n"); + } + return sb.toString(); + } + + public void openRange(char start) { + if (!hasOpenRange()) { + aliveRanges.add(new Range(start)); + } } + + public void closeRange(char length) { + if (isLastRangeInitialized() && length > 0) { + Range range = lastRange(); + if (range != null) { + if (range.length == Character.MAX_VALUE) { + range.length = length; + } + } + } else { + removeLastRange(); + } + } + + public boolean hasOpenRange() { + if (aliveRanges.isEmpty()) { + return false; + } + return lastRange().length == Character.MAX_VALUE; + } + + public boolean isLastRangeInitialized() { + if (aliveRanges.isEmpty()) { + return false; + } + return lastRange().start_pc != Character.MAX_VALUE; + } + + public Range getWidestRange() { + if (aliveRanges.isEmpty()) { + return new Range(); + } else { + Range firstRange = firstRange(); + Range lastRange = lastRange(); + char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc)); + return new Range(firstRange.start_pc, length); + } + } }; /** Local variables, indexed by register. */ @@ -1858,6 +1965,30 @@ state.defined.excl(adr); } + void adjustAliveRanges(int oldCP, int delta) { + for (LocalVar localVar: lvar) { + if (localVar != null) { + for (LocalVar.Range range: localVar.aliveRanges) { + if (range.closed() && range.start_pc + range.length >= oldCP) { + range.length += delta; + } + } + } + } + } + + /** + * Calculates the size of the LocalVariableTable. + */ + public int getLVTSize() { + int result = varBufferSize; + for (int i = 0; i < varBufferSize; i++) { + LocalVar var = varBuffer[i]; + result += var.aliveRanges.size() - 1; + } + return result; + } + /** Set the current variable defined state. */ public void setDefined(Bits newDefined) { if (alive && newDefined != state.defined) { @@ -1883,8 +2014,7 @@ } else { state.defined.incl(adr); if (cp < Character.MAX_VALUE) { - if (v.start_pc == Character.MAX_VALUE) - v.start_pc = (char)cp; + v.openRange((char)cp); } } } @@ -1894,15 +2024,15 @@ state.defined.excl(adr); if (adr < lvar.length && lvar[adr] != null && - lvar[adr].start_pc != Character.MAX_VALUE) { + lvar[adr].isLastRangeInitialized()) { LocalVar v = lvar[adr]; - char length = (char)(curPc() - v.start_pc); + char length = (char)(curPc()- v.lastRange().start_pc); if (length > 0 && length < Character.MAX_VALUE) { lvar[adr] = v.dup(); - v.length = length; + v.closeRange(length); putVar(v); } else { - v.start_pc = Character.MAX_VALUE; + v.removeLastRange(); } } } @@ -1912,10 +2042,10 @@ LocalVar v = lvar[adr]; if (v != null) { lvar[adr] = null; - if (v.start_pc != Character.MAX_VALUE) { - char length = (char)(curPc() - v.start_pc); + if (v.isLastRangeInitialized()) { + char length = (char)(curPc()- v.lastRange().start_pc); if (length < Character.MAX_VALUE) { - v.length = length; + v.closeRange(length); putVar(v); } }
--- a/test/tools/javac/6889255/T6889255.java Tue Mar 10 15:41:40 2015 -0700 +++ b/test/tools/javac/6889255/T6889255.java Tue Mar 10 15:49:28 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -429,9 +429,9 @@ // -- no Code attribute for the LocalVariableTable attribute if ((v.owner.flags() & Flags.ABSTRACT) != 0) return "arg" + (i - 1); - // bridge methods use xN + // bridge methods use argN. No LVT for them anymore if ((v.owner.flags() & Flags.BRIDGE) != 0) - return "x" + (i - 1); + return "arg" + (i - 1); // The rest of this method assumes the local conventions in the test program Type t = v.type;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6695379/AnnotationsAreNotCopiedToBridgeMethodsTest.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, 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 6695379 + * @summary Copy method annotations and parameter annotations to synthetic + * bridge methods + * @run main AnnotationsAreNotCopiedToBridgeMethodsTest + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.io.BufferedInputStream; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.sun.tools.classfile.AccessFlags; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Attributes; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Method; +import com.sun.tools.javac.util.Assert; + +public class AnnotationsAreNotCopiedToBridgeMethodsTest { + + public static void main(String[] args) throws Exception { + new AnnotationsAreNotCopiedToBridgeMethodsTest().run(); + } + + void run() throws Exception { + checkClassFile(Paths.get(System.getProperty("test.classes"), + this.getClass().getSimpleName() + "$CovariantReturnType.class")); + checkClassFile(Paths.get(System.getProperty("test.classes"), + this.getClass().getSimpleName() + + "$CovariantReturnType$VisibilityChange.class")); + } + + void checkClassFile(final Path cfilePath) throws Exception { + ClassFile classFile = ClassFile.read( + new BufferedInputStream(Files.newInputStream(cfilePath))); + for (Method method : classFile.methods) { + if (method.access_flags.is(AccessFlags.ACC_BRIDGE)) { + checkForAttr(method.attributes, + "Annotations hasn't been copied to bridge method", + Attribute.RuntimeVisibleAnnotations, + Attribute.RuntimeVisibleParameterAnnotations); + } + } + } + + void checkForAttr(Attributes attrs, String errorMsg, String... attrNames) { + for (String attrName : attrNames) { + Assert.checkNonNull(attrs.get(attrName), errorMsg); + } + } + + @Target(value = {ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + @interface ParamAnnotation {} + + @Target(value = {ElementType.METHOD}) + @Retention(RetentionPolicy.RUNTIME) + @interface MethodAnnotation {} + + abstract class T<A,B> { + B m(A a){return null;} + } + + class CovariantReturnType extends T<Integer, Integer> { + @MethodAnnotation + Integer m(@ParamAnnotation Integer i) { + return i; + } + + public class VisibilityChange extends CovariantReturnType {} + + } + +}
--- a/test/tools/javac/annotations/6214965/T6214965.java Tue Mar 10 15:41:40 2015 -0700 +++ b/test/tools/javac/annotations/6214965/T6214965.java Tue Mar 10 15:49:28 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -23,9 +23,10 @@ /** * @test - * @bug 6214965 6365854 + * @bug 6214965 6365854 8068639 * @summary Compiler crash on redefing nested annotation types * @compile CompilerAnnotationTest.java CompilerAnnotationTest2.java * @compile CompilerAnnotationTest2bad.java - * @compile/ref=T6214965.out -XDrawDiagnostics CompilerAnnotationTest2bad.java + * @compile/ref=T6214965.out -XDrawDiagnostics -Xlint:classfile CompilerAnnotationTest2bad.java + * @compile -Werror CompilerAnnotationTest2bad.java */
--- a/test/tools/javac/annotations/6365854/T6365854.java Tue Mar 10 15:41:40 2015 -0700 +++ b/test/tools/javac/annotations/6365854/T6365854.java Tue Mar 10 15:49:28 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 6365854 + * @bug 6365854 8068639 * @summary javac crashes when compiling against an annotated class * @compile TestAnnotation.java TestCore.java * @clean test.annotation.TestAnnotation @@ -33,11 +33,11 @@ * * @compile TestAnnotation.java TestCore.java * @clean test.annotation.TestAnnotation - * @compile/ref=test1.out -XDrawDiagnostics T6365854.java + * @compile/ref=test1.out -XDrawDiagnostics -Xlint:classfile T6365854.java * @run main T6365854 - * @compile/ref=test2.out -XDrawDiagnostics evolve/TestAnnotation.java T6365854.java + * @compile/ref=test2.out -XDrawDiagnostics -Xlint:classfile evolve/TestAnnotation.java T6365854.java * @run main T6365854 - * @compile/ref=test2.out -XDrawDiagnostics T6365854.java + * @compile/ref=test2.out -XDrawDiagnostics -Xlint:classfile T6365854.java * @run main T6365854 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/annotations/clinit/AnnoWithClinit1.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013, 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 8013485 + * @summary Annotations that gets a clinit can't be verified for correct elements in a second compilation unit + * @compile AnnoWithClinit1.java + */ + +public @interface AnnoWithClinit1 { + Foo f = new Foo(); + + @AnnoWithClinit1 + static class C {} // this is in the same CU so there wont be a + // <clinit> when the this anno instance is checked + + class Foo {} +} + + +@AnnoWithClinit1 +class BarAnnoClinit1 {} + +@interface AAnnoClinit1 { + Runnable r2 = new Runnable() { public void run() { }}; + String str1(); + String str2withdefault() default "bar"; +} + +@AAnnoClinit1(str1="value") +class TestAnnoClinit1 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/annotations/clinit/AnnoWithClinitFail.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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 8013485 + * @summary Annotations that gets a clinit can't be verified for correct elements in a second compilation unit + * @compile/fail/ref=AnnoWithClinitFail.out -XDrawDiagnostics AnnoWithClinitFail.java + */ + +public @interface AnnoWithClinitFail { + Foo f = new Foo(); + + String foo(); + String bar() default "bar"; + + @AnnoWithClinitFail + static class C {} // this is in the same CU so there wont be a + // <clinit> when the this anno instance is checked + + class Foo {} +} + +@AnnoWithClinitFail +class TestAnnoWithClinitFail { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/annotations/clinit/AnnoWithClinitFail.out Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,3 @@ +AnnoWithClinitFail.java:37:5: compiler.err.annotation.missing.default.value: AnnoWithClinitFail, foo +AnnoWithClinitFail.java:44:1: compiler.err.annotation.missing.default.value: AnnoWithClinitFail, foo +2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/DARanges.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, 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. + */ +import java.lang.annotation.*; + +@Target({ElementType.METHOD}) +@interface DARange { + String varName(); + int bytecodeStart(); + int bytecodeLength(); +} + +@Target({ElementType.METHOD}) +@interface DARanges {DARange[] value();}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/LVTHarness.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2014, 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 8058708 + * @summary The LVT is not generated correctly during some try/catch scenarios + * javac crash while creating LVT entry for a local variable defined in + * an inner block + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor LVTHarness + * @run main LVTHarness + */ + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Set; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.ConstantPool.InvalidIndex; +import com.sun.tools.classfile.ConstantPool.UnexpectedEntry; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.LocalVariableTable_attribute; +import com.sun.tools.classfile.Method; + +import static javax.tools.StandardLocation.*; +import static com.sun.tools.classfile.LocalVariableTable_attribute.Entry; +import static javax.tools.JavaFileObject.Kind.SOURCE; + +public class LVTHarness { + + static int nerrors = 0; + + static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + public static void main(String[] args) throws Exception { + + String testDir = System.getProperty("test.src"); + fm.setLocation(SOURCE_PATH, Arrays.asList(new File(testDir, "tests"))); + + // Make sure classes are written to scratch dir. + fm.setLocation(CLASS_OUTPUT, Arrays.asList(new File("."))); + + for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(SOURCE), true)) { + new LVTHarness(jfo).check(); + } + if (nerrors > 0) { + throw new AssertionError("Errors were found"); + } + } + + + JavaFileObject jfo; + Map<ElementKey, DARanges> aliveRangeMap = new HashMap<ElementKey, DARanges>(); + Set<String> declaredKeys = new HashSet<String>(); + List<ElementKey> seenDARanges = new ArrayList<ElementKey>(); + + protected LVTHarness(JavaFileObject jfo) { + this.jfo = jfo; + } + + protected void check() throws Exception { + + JavacTask ct = (JavacTask) comp.getTask(null, fm, null, Arrays.asList("-g"), + null, Arrays.asList(jfo)); + System.err.println("compiling code " + jfo); + ct.setProcessors(Collections.singleton(new DARangeFinder())); + if (!ct.call()) { + throw new AssertionError("Error during compilation"); + } + + + File javaFile = new File(jfo.getName()); + File classFile = new File(javaFile.getName().replace(".java", ".class")); + checkClassFile(classFile); + + //check all candidates have been used up + for (Map.Entry<ElementKey, DARanges> entry : aliveRangeMap.entrySet()) { + if (!seenDARanges.contains(entry.getKey())) { + error("Redundant @DARanges annotation on method " + + entry.getKey().elem + " with key " + entry.getKey()); + } + } + } + + void checkClassFile(File file) + throws IOException, ConstantPoolException, InvalidDescriptor { + ClassFile classFile = ClassFile.read(file); + ConstantPool constantPool = classFile.constant_pool; + + //lets get all the methods in the class file. + for (Method method : classFile.methods) { + for (ElementKey elementKey: aliveRangeMap.keySet()) { + String methodDesc = method.getName(constantPool) + + method.descriptor.getParameterTypes(constantPool).replace(" ", ""); + if (methodDesc.equals(elementKey.elem.toString())) { + checkMethod(constantPool, method, aliveRangeMap.get(elementKey)); + seenDARanges.add(elementKey); + } + } + } + } + + void checkMethod(ConstantPool constantPool, Method method, DARanges ranges) + throws InvalidIndex, UnexpectedEntry { + Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); + LocalVariableTable_attribute lvt = + (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); + List<String> infoFromRanges = convertToStringList(ranges); + List<String> infoFromLVT = convertToStringList(constantPool, lvt); + + // infoFromRanges most be contained in infoFromLVT + int i = 0; + int j = 0; + while (i < infoFromRanges.size() && j < infoFromLVT.size()) { + int comparison = infoFromRanges.get(i).compareTo(infoFromLVT.get(j)); + if (comparison == 0) { + i++; j++; + } else if (comparison > 0) { + j++; + } else { + break; + } + } + + if (i < infoFromRanges.size()) { + error(infoFromLVT, infoFromRanges); + } + } + + List<String> convertToStringList(DARanges ranges) { + List<String> result = new ArrayList<String>(); + for (Annotation anno : ranges.value()) { + DARange range = (DARange)anno; + String str = formatLocalVariableData(range.varName(), + range.bytecodeStart(), range.bytecodeLength()); + result.add(str); + } + Collections.sort(result); + return result; + } + + List<String> convertToStringList(ConstantPool constantPool, + LocalVariableTable_attribute lvt) throws InvalidIndex, UnexpectedEntry { + List<String> result = new ArrayList<String>(); + for (Entry entry : lvt.local_variable_table) { + String str = formatLocalVariableData(constantPool.getUTF8Value(entry.name_index), + entry.start_pc, entry.length); + result.add(str); + } + Collections.sort(result); + return result; + } + + String formatLocalVariableData(String varName, int start, int length) { + StringBuilder sb = new StringBuilder() + .append("var name: ").append(varName) + .append(" start: ").append(start) + .append(" length: ").append(length); + return sb.toString(); + } + + protected void error(List<String> infoFromLVT, List<String> infoFromRanges) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\n", jfo.getName()); + System.err.println("The range info from the annotations is"); + printStringListToErrOutput(infoFromRanges); + System.err.println(); + System.err.println("And the range info from the class file is"); + printStringListToErrOutput(infoFromLVT); + System.err.println(); + } + + void printStringListToErrOutput(List<String> list) { + for (String s : list) { + System.err.println("\t" + s); + } + } + + protected void error(String msg) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\nreason: %s\n", + jfo.getName(), msg); + } + + class DARangeFinder extends JavacTestingAbstractProcessor { + + @Override + public boolean process(Set<? extends TypeElement> annotations, + RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) + return true; + + TypeElement aliveRangeAnno = elements.getTypeElement("DARanges"); + + if (!annotations.contains(aliveRangeAnno)) { + error("no @DARanges annotation found in test class"); + } + + for (Element elem: roundEnv.getElementsAnnotatedWith(aliveRangeAnno)) { + Annotation annotation = elem.getAnnotation(DARanges.class); + aliveRangeMap.put(new ElementKey(elem), (DARanges)annotation); + } + return true; + } + } + + class ElementKey { + + String key; + Element elem; + + public ElementKey(Element elem) { + this.elem = elem; + this.key = computeKey(elem); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ElementKey) { + ElementKey other = (ElementKey)obj; + return other.key.equals(key); + } + return false; + } + + @Override + public int hashCode() { + return key.hashCode(); + } + + String computeKey(Element e) { + StringBuilder buf = new StringBuilder(); + while (e != null) { + buf.append(e.toString()); + e = e.getEnclosingElement(); + } + buf.append(jfo.getName()); + return buf.toString(); + } + + @Override + public String toString() { + return "Key{" + key + "}"; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseConditional.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,15 @@ +public class TestCaseConditional { + @DARanges({ + @DARange(varName="o", bytecodeStart=5, bytecodeLength=33), + @DARange(varName="oo", bytecodeStart=23, bytecodeLength=15) + }) + void m(String[] args) { + Boolean o; + Boolean oo = ((o = Boolean.TRUE).booleanValue()) ? + o = Boolean.TRUE : + Boolean.FALSE; + oo.hashCode(); + o = Boolean.FALSE; + o.hashCode(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseDoLoop.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,15 @@ +public class TestCaseDoLoop { + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=15), + @DARange(varName="args", bytecodeStart=0, bytecodeLength=18) + }) + void m(String[] args) { + Object o; + do { + o = ""; + o.hashCode(); + } while (args[0] != null); + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseFor.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,29 @@ +public class TestCaseFor { + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=11), + @DARange(varName="o", bytecodeStart=24, bytecodeLength=1) + }) + void m1(String[] args) { + Object o; + for (int i = 0; i < 5; i++) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=11), + @DARange(varName="o", bytecodeStart=24, bytecodeLength=1) + }) + void m2(String[] args) { + Object o; + for (int i = 0; i < 5; i++) { + o = ""; + o.hashCode(); + continue; + } + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseForEach.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,15 @@ +public class TestCaseForEach { + + @DARanges({ + @DARange(varName="o", bytecodeStart=25, bytecodeLength=11), + @DARange(varName="o", bytecodeStart=39, bytecodeLength=1) + }) + void m(String[] args) { + Object o; + for (String s : args) { + o = ""; + o.hashCode(); + } + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseIf.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,84 @@ +public class TestCaseIf { + @DARanges({ + @DARange(varName="o", bytecodeStart=9, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=17, bytecodeLength=1) + }) + void m0(String[] args) { + Object o; + if (args[0] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=18, bytecodeLength=1) + }) + void m1() { + Object o; + int i = 5; + if (i == 5) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=18, bytecodeLength=1) + }) + void m2() { + Object o; + int i = 5; + if (!(i == 5)) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=15, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=1) + }) + void m3(String[] args) { + Object o; + if (args[0] != null && args[1] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=15, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=1) + }) + void m4(String[] args) { + Object o; + if (args[0] != null || args[1] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="finalLocal", bytecodeStart=11, bytecodeLength=6), + @DARange(varName="used", bytecodeStart=13, bytecodeLength=4) + }) + void m5(Object o) { + if (o != null) { + Object notUsed; + Object used; + if (o != null) { + final Object finalLocal = null; + used = null; + if (o == null) {} + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseIfElse.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,69 @@ +public class TestCaseIfElse { + + @DARanges({ + @DARange(varName="o", bytecodeStart=9, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=20, bytecodeLength=9) + }) + void m0(String[] args) { + Object o; + if (args[0] != null) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=21, bytecodeLength=9) + }) + void m1() { + Object o; + int i = 5; + if (i == 5) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=10, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=21, bytecodeLength=9) + }) + void m2() { + Object o; + int i = 5; + if (i != 5) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=11, bytecodeLength=3), + @DARange(varName="o", bytecodeStart=17, bytecodeLength=2) + }) + Object m3(boolean cond1, boolean cond2) { + Object o; + if (cond1) { + if (cond2) { + o = "then"; + } else { + o = "else"; + return null; + } + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseLocalInInnerBlock.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,20 @@ +public class TestCaseLocalInInnerBlock { + + @DARanges({ + @DARange(varName="fm", bytecodeStart=23, bytecodeLength=10), + @DARange(varName="newWidth", bytecodeStart=2, bytecodeLength=33), + @DARange(varName="tc", bytecodeStart=5, bytecodeLength=30) + }) + int m() { + int newWidth = 0; + String tc = "b"; + if (tc != null) { + String fm; + if (tc.trim() != null) { + } else if ((fm = "b") != null) { + newWidth += fm.length(); + } + } + return newWidth; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseSwitch.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,86 @@ +public class TestCaseSwitch { + + @DARanges({ + @DARange(varName="o", bytecodeStart=31, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=50, bytecodeLength=15), + @DARange(varName="o", bytecodeStart=68, bytecodeLength=1), + @DARange(varName="oo", bytecodeStart=39, bytecodeLength=8), + @DARange(varName="uu", bytecodeStart=59, bytecodeLength=6) + }) + void m1(String[] args) { + Object o; + switch (args.length) { + case 0: + o = "0"; + o.hashCode(); + Object oo = "oo"; + oo.hashCode(); + break; + case 1: + o = "1"; + o.hashCode(); + Object uu = "uu"; + uu.hashCode(); + break; + } + o = "return"; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=35, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=46, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=78, bytecodeLength=5), + @DARange(varName="o", bytecodeStart=86, bytecodeLength=1), + @DARange(varName="oo", bytecodeStart=56, bytecodeLength=16) + }) + void m3(int i) { + Object o; + switch (i) { + case 0: + o = "0"; + o.hashCode(); + break; + case 1: + o = "1"; + o.hashCode(); + break; + case 2: + int oo = i; + if (oo > 1) { + System.out.println("greater"); + } + break; + case 3: + int uu = i; + default: + o = "default"; + o.hashCode(); + } + o = "finish"; + } + + @DARanges({ + @DARange(varName="oCache", bytecodeStart=30, bytecodeLength=6), + @DARange(varName="cache", bytecodeStart=41, bytecodeLength=3), + @DARange(varName="cache", bytecodeStart=54, bytecodeLength=2), + @DARange(varName="service", bytecodeStart=39, bytecodeLength=5) + }) + public Object m(int i) { + Object cache; + switch (i) { + case 0: + Object oCache = null; + if (oCache != null) { + return oCache; + } + case 1: + Object service = null; + cache = null; + break; + default: + throw new AssertionError(""); + } + return cache; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseTry.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,55 @@ +public class TestCaseTry { + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=15, bytecodeLength=1) + }) + void m0(String[] args) { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) {} + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=35, bytecodeLength=11) + }) + void m1() { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) { + } + finally { + o = "finally"; + o.hashCode(); + } + o = ""; + } + + @DARanges({ + @DARange(varName="o", bytecodeStart=3, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=23, bytecodeLength=16), + @DARange(varName="o", bytecodeStart=43, bytecodeLength=11) + }) + void m2() { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) { + o = "catch"; + o.hashCode(); + } + finally { + o = "finally"; + o.hashCode(); + } + o = ""; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/tests/TestCaseWhile.java Tue Mar 10 15:49:28 2015 -0700 @@ -0,0 +1,15 @@ +public class TestCaseWhile { + + @DARanges({ + @DARange(varName="o", bytecodeStart=9, bytecodeLength=8), + @DARange(varName="o", bytecodeStart=20, bytecodeLength=1) + }) + void m(String[] args) { + Object o; + while (args[0] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } +}