Commit 4accca37 authored by ebruneton's avatar ebruneton

workaround for a javac bug (see asm bug report #307392)

parent c6079dff
......@@ -281,15 +281,20 @@ final class AnnotationWriter implements AnnotationVisitor {
* Puts the given annotation lists into the given byte vector.
*
* @param panns an array of annotation writer lists.
* @param off index of the first annotation to be written.
* @param out where the annotations must be put.
*/
static void put(final AnnotationWriter[] panns, final ByteVector out) {
int size = 1 + 2 * panns.length;
for (int i = 0; i < panns.length; ++i) {
static void put(
final AnnotationWriter[] panns,
final int off,
final ByteVector out)
{
int size = 1 + 2 * (panns.length - off);
for (int i = off; i < panns.length; ++i) {
size += panns[i] == null ? 0 : panns[i].getSize();
}
out.putInt(size).putByte(panns.length);
for (int i = 0; i < panns.length; ++i) {
out.putInt(size).putByte(panns.length - off);
for (int i = off; i < panns.length; ++i) {
AnnotationWriter aw = panns[i];
AnnotationWriter last = null;
int n = 0;
......
......@@ -848,10 +848,10 @@ public class ClassReader {
}
}
if (ANNOTATIONS && mpanns != 0) {
readParameterAnnotations(mpanns, c, true, mv);
readParameterAnnotations(mpanns, desc, c, true, mv);
}
if (ANNOTATIONS && impanns != 0) {
readParameterAnnotations(impanns, c, false, mv);
readParameterAnnotations(impanns, desc, c, false, mv);
}
while (cattrs != null) {
attr = cattrs.next;
......@@ -1460,6 +1460,7 @@ public class ClassReader {
* Reads parameter annotations and makes the given visitor visit them.
*
* @param v start offset in {@link #b b} of the annotations to be read.
* @param desc the method descriptor.
* @param buf buffer to be used to call {@link #readUTF8 readUTF8},
* {@link #readClass(int,char[]) readClass} or
* {@link #readConst readConst}.
......@@ -1469,21 +1470,34 @@ public class ClassReader {
*/
private void readParameterAnnotations(
int v,
final String desc,
final char[] buf,
final boolean visible,
final MethodVisitor mv)
{
int i;
int n = b[v++] & 0xFF;
for (int i = 0; i < n; ++i) {
// workaround for a bug in javac (javac compiler generates a parameter
// annotation array whose size is equal to the number of parameters in
// the Java source file, while it should generate an array whose size is
// equal to the number of parameters in the method descriptor - which
// includes the synthetic parameters added by the compiler). This work-
// around supposes that the synthetic parameters are the first ones.
int synthetics = Type.getArgumentTypes(desc).length - n;
AnnotationVisitor av;
for (i = 0; i < synthetics; ++i) {
// virtual annotation to detect synthetic parameters in MethodWriter
av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
if (av != null) {
av.visitEnd();
}
}
for (; i < n + synthetics; ++i) {
int j = readUnsignedShort(v);
v += 2;
for (; j > 0; --j) {
v = readAnnotationValues(v + 2,
buf,
true,
mv.visitParameterAnnotation(i,
readUTF8(v, buf),
visible));
av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
v = readAnnotationValues(v + 2, buf, true, av);
}
}
}
......
......@@ -208,6 +208,11 @@ class MethodWriter implements MethodVisitor {
*/
private AnnotationWriter[] ipanns;
/**
* The number of synthetic parameters of this method.
*/
private int synthetics;
/**
* The non standard attributes of the method.
*/
......@@ -494,6 +499,12 @@ class MethodWriter implements MethodVisitor {
return null;
}
ByteVector bv = new ByteVector();
if ("Ljava/lang/Synthetic;".equals(desc)) {
// workaround for a bug in javac with synthetic parameters
// see ClassReader.readParameterAnnotations
synthetics = Math.max(synthetics, parameter + 1);
return new AnnotationWriter(cw, false, bv, null, 0);
}
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
......@@ -1844,15 +1855,15 @@ class MethodWriter implements MethodVisitor {
}
if (ClassReader.ANNOTATIONS && panns != null) {
cw.newUTF8("RuntimeVisibleParameterAnnotations");
size += 7 + 2 * panns.length;
for (int i = panns.length - 1; i >= 0; --i) {
size += 7 + 2 * (panns.length - synthetics);
for (int i = panns.length - 1; i >= synthetics; --i) {
size += panns[i] == null ? 0 : panns[i].getSize();
}
}
if (ClassReader.ANNOTATIONS && ipanns != null) {
cw.newUTF8("RuntimeInvisibleParameterAnnotations");
size += 7 + 2 * ipanns.length;
for (int i = ipanns.length - 1; i >= 0; --i) {
size += 7 + 2 * (ipanns.length - synthetics);
for (int i = ipanns.length - 1; i >= synthetics; --i) {
size += ipanns[i] == null ? 0 : ipanns[i].getSize();
}
}
......@@ -2024,11 +2035,11 @@ class MethodWriter implements MethodVisitor {
}
if (ClassReader.ANNOTATIONS && panns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
AnnotationWriter.put(panns, out);
AnnotationWriter.put(panns, synthetics, out);
}
if (ClassReader.ANNOTATIONS && ipanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));
AnnotationWriter.put(ipanns, out);
AnnotationWriter.put(ipanns, synthetics, out);
}
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
......
......@@ -163,6 +163,7 @@ org/objectweb/asm/MethodWriter.previousBlock=O
org/objectweb/asm/MethodWriter.currentBlock=P
org/objectweb/asm/MethodWriter.stackSize=Q
org/objectweb/asm/MethodWriter.maxStackSize=R
org/objectweb/asm/MethodWriter.synthetics=S
org/objectweb/asm/Type.sort=a
org/objectweb/asm/Type.buf=b
......@@ -179,7 +180,7 @@ org/objectweb/asm/signature/SignatureWriter.argumentStack=d
# method mappings
org/objectweb/asm/AnnotationWriter.getSize()I=a
org/objectweb/asm/AnnotationWriter.put([Lorg/objectweb/asm/AnnotationWriter;Lorg/objectweb/asm/ByteVector;)V=a
org/objectweb/asm/AnnotationWriter.put([Lorg/objectweb/asm/AnnotationWriter;ILorg/objectweb/asm/ByteVector;)V=a
org/objectweb/asm/AnnotationWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
org/objectweb/asm/Attribute.getCount()I=a
......@@ -195,7 +196,7 @@ org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/obje
org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=a
org/objectweb/asm/ClassReader.readAttribute([Lorg/objectweb/asm/Attribute;Ljava/lang/String;II[CI[Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Attribute;=a
org/objectweb/asm/ClassReader.readClass(Ljava/io/InputStream;)[B=a
org/objectweb/asm/ClassReader.readParameterAnnotations(I[CZLorg/objectweb/asm/MethodVisitor;)V=a
org/objectweb/asm/ClassReader.readParameterAnnotations(ILjava/lang/String;[CZLorg/objectweb/asm/MethodVisitor;)V=a
org/objectweb/asm/ClassReader.readUTF(II[C)Ljava/lang/String;=a
org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=a
......
......@@ -293,13 +293,15 @@ public class Annotation extends Generator {
fv.visitEnd();
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(IIIIIIIIII)V", null, null);
// visible method anntation
// visible method annotation
mv.visitAnnotation(DEPRECATED, true).visitEnd();
// invisible method annotation
av0 = mv.visitAnnotation("Lpkg/Annotation;", false);
av0.visitAnnotation("annotationValue", DOC).visitEnd();
av0.visitEnd();
// visible parameter annnotation
// synthetic parameter annotation
mv.visitParameterAnnotation(0, "Ljava/lang/Synthetic;", false);
// visible parameter annotation
mv.visitParameterAnnotation(8, DEPRECATED, true).visitEnd();
// invisible parameter annotation
av0 = mv.visitParameterAnnotation(8, "Lpkg/Annotation;", false);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment