]> source.dussan.org Git - javassist.git/commitdiff
fixed Bugs item #997458: addCatch("return;", ...) on CtConstructor causes VerifyError
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Tue, 27 Jul 2004 09:45:50 +0000 (09:45 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Tue, 27 Jul 2004 09:45:50 +0000 (09:45 +0000)
implemented CtBehavior#addLocalVariable()

git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@118 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/CtBehavior.java
src/main/javassist/CtConstructor.java
src/main/javassist/bytecode/LocalVariableAttribute.java

index 01f907cf47dd82fd65a48b9b94281b79f6bdbb4f..0ed161de2c42cb6dcec76aee49ce10fce0697335 100644 (file)
@@ -299,6 +299,40 @@ public abstract class CtBehavior extends CtMember {
         }
     }
 
+    /**
+     * Declares a new local variable.  The scope of this variable is the
+     * whole method body.  The initial value of that variable is not set.
+     * The declared variable can be accessed in the code snippet inserted
+     * by <code>insertBefore()</code>, <code>insertAfter()</code>, etc.
+     *
+     * @param name      the name of the variable
+     * @param type      the type of the variable
+     * @see #insertBefore(String)
+     * @see #insertAfter(String)
+     */
+    public void addLocalVariable(String name, CtClass type)
+        throws CannotCompileException
+    {
+        declaringClass.checkModify();
+        ConstPool cp = methodInfo.getConstPool();
+        CodeAttribute ca = methodInfo.getCodeAttribute();
+        if (ca == null)
+            throw new CannotCompileException("no method body");
+
+        LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute(
+                                                LocalVariableAttribute.tag);
+        if (va == null) {
+            va = new LocalVariableAttribute(cp);
+            ca.getAttributes().add(va);
+        }
+
+        int maxLocals = ca.getMaxLocals();
+        String desc = Descriptor.of(type);
+        va.addEntry(0, ca.getCodeLength(),
+                    cp.addUtf8Info(name), cp.addUtf8Info(desc), maxLocals);
+        ca.setMaxLocals(maxLocals + Descriptor.dataSize(desc));
+    }
+
     /**
      * Modifies the method/constructor body.
      *
@@ -357,6 +391,7 @@ public abstract class CtBehavior extends CtMember {
             int nvars = jv.recordParams(getParameterTypes(),
                                         Modifier.isStatic(getModifiers()));
             jv.recordParamNames(ca, nvars);
+            jv.recordLocalVariables(ca, 0);
             jv.compileStmnt(src);
             Bytecode b = jv.getBytecode();
             int stack = b.getMaxStack();
@@ -426,6 +461,7 @@ public abstract class CtBehavior extends CtMember {
             jv.recordParamNames(ca, nvars);
             CtClass rtype = getReturnType0();
             int varNo = jv.recordReturnType(rtype, true);
+            jv.recordLocalVariables(ca, 0);
 
             int handlerLen = insertAfterHandler(asFinally, b, rtype, varNo);
 
@@ -675,7 +711,7 @@ public abstract class CtBehavior extends CtMember {
 
             int len = iterator.getCodeLength();
             int pos = iterator.append(b.get());
-            ca.getExceptionTable().add(0, len, len,
+            ca.getExceptionTable().add(getStartPosOfBody(ca), len, len,
                                        cp.addClassInfo(exceptionType));
             iterator.append(b.getExceptionTable(), pos);
         }
@@ -687,6 +723,12 @@ public abstract class CtBehavior extends CtMember {
         }
     }
 
+    /* CtConstructor overrides this method.
+     */
+    int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException {
+        return 0;
+    }
+
     /**
      * Inserts bytecode at the specified line in the body.
      * It is equivalent to:
index e294ca515b2f60367d0233cb435838c7c0f48fc5..72dcee11e5c08542f2f2823dc95a6349e70069ae 100644 (file)
@@ -284,4 +284,18 @@ public final class CtConstructor extends CtBehavior {
             throw new CannotCompileException(e);
         }
     }
+
+    /* This method is called by addCatch() in CtBehavior.
+     * super() and this() must not be in a try statement.
+     */
+    int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException {
+        CodeIterator ci = ca.iterator();
+        try {
+            ci.skipConstructor();
+            return ci.next();
+        }
+        catch (BadBytecode e) {
+            throw new CannotCompileException(e);
+        }
+    }
 }
index a88dfac75c2d36feca0dbc977f4050105a8357cf..ab66f67637bf3956c47775038df69e0a78567c81 100644 (file)
@@ -34,6 +34,14 @@ public class LocalVariableAttribute extends AttributeInfo {
      */
     public static final String typeTag = "LocalVariableTypeTable";
 
+    /**
+     * Constructs an empty LocalVariableTable.
+     */
+    public LocalVariableAttribute(ConstPool cp) {
+        super(cp, tag, new byte[2]);
+        ByteArray.write16bit(0, info, 0);
+    }
+
     LocalVariableAttribute(ConstPool cp, int n, DataInputStream in)
         throws IOException
     {
@@ -44,6 +52,31 @@ public class LocalVariableAttribute extends AttributeInfo {
         super(cp, tag, i);
     }
 
+    /**
+     * Appends a new entry to <code>local_variable_table</code>.
+     *
+     * @param startPc           <code>start_pc</code>
+     * @param length            <code>length</code>
+     * @param nameIndex         <code>name_index</code>
+     * @param descriptorIndex   <code>descriptor_index</code>
+     * @param index             <code>index</code>
+     */
+    public void addEntry(int startPc, int length, int nameIndex,
+                         int descriptorIndex, int index) {
+        int size = info.length;
+        byte[] newInfo = new byte[size + 10];
+        ByteArray.write16bit(tableLength() + 1, newInfo, 0);
+        for (int i = 2; i < size; ++i)
+            newInfo[i] = info[i];
+
+        ByteArray.write16bit(startPc, newInfo, size);
+        ByteArray.write16bit(length, newInfo, size + 2);
+        ByteArray.write16bit(nameIndex, newInfo, size + 4);
+        ByteArray.write16bit(descriptorIndex, newInfo, size + 6);
+        ByteArray.write16bit(index, newInfo, size + 8);
+        info = newInfo;
+    }
+
     /**
      * Returns <code>local_variable_table_length</code>.
      * This represents the number of entries in the table.
@@ -83,7 +116,10 @@ public class LocalVariableAttribute extends AttributeInfo {
             int pos = i * 10 + 2;
             int pc = ByteArray.readU16bit(info, pos);
             int len = ByteArray.readU16bit(info, pos + 2);
-            if (pc > where || (exclusive && pc == where))
+
+            /* if pc == 0, then the local variable is a method parameter.
+             */
+            if (pc > where || (exclusive && pc == where && pc != 0))
                 ByteArray.write16bit(pc + gapLength, info, pos);
             else if (pc + len > where)
                 ByteArray.write16bit(len + gapLength, info, pos + 2);