class Cache extends CtMember {
        @Override
        protected void extendToString(StringBuffer buffer) {}
        @Override
        public boolean hasAnnotation(String clz) { return false; }
        @Override
        public Object getAnnotation(Class<?> clz)
            throws ClassNotFoundException { return null; }
        @Override
        public Object[] getAnnotations()
            throws ClassNotFoundException { return null; }
        @Override
        public byte[] getAttribute(String name) { return null; }
        @Override
        public Object[] getAvailableAnnotations() { return null; }
        @Override
        public int getModifiers() { return 0; }
        @Override
        public String getName() { return null; }
        @Override
        public String getSignature() { return null; }
        @Override
        public void setAttribute(String name, byte[] data) {}
        @Override
        public void setModifiers(int mod) {}
        @Override
        public String getGenericSignature() { return null; }
        @Override
        public void setGenericSignature(String sig) {}

        private CtMember methodTail;
        private CtMember consTail;     // constructor tail
        private CtMember fieldTail;

        Cache(CtClassType decl) {
            super(decl);
            methodTail = this;
            consTail = this;
            fieldTail = this;
            fieldTail.next = this;
        }

        CtMember methodHead() { return this; }
        CtMember lastMethod() { return methodTail; }
        CtMember consHead() { return methodTail; }      // may include a static initializer
        CtMember lastCons() { return consTail; }
        CtMember fieldHead() { return consTail; }
        CtMember lastField() { return fieldTail; }

        void addMethod(CtMember method) {
            method.next = methodTail.next;
            methodTail.next = method;
            if (methodTail == consTail) {
                consTail = method;
                if (methodTail == fieldTail)
                    fieldTail = method;
            }

            methodTail = method;
        }

        /* Both constructors and a class initializer.
         */
        void addConstructor(CtMember cons) {
            cons.next = consTail.next;
            consTail.next = cons;
            if (consTail == fieldTail)
                fieldTail = cons;

            consTail = cons;
        }

        void addField(CtMember field) {
            field.next = this; // or fieldTail.next
            fieldTail.next = field;
            fieldTail = field;
        }

        static int count(CtMember head, CtMember tail) {
            int n = 0;
            while (head != tail) {
                n++;
                head = head.next;
            }

            return n;
        }

        void remove(CtMember mem) {
            CtMember m = this;
            CtMember node;
            while ((node = m.next) != this) {
                if (node == mem) {
                    m.next = node.next;
                    if (node == methodTail)
                        methodTail = m;

                    if (node == consTail)
                        consTail = m;

                    if (node == fieldTail)
                        fieldTail = m;

                    break;
                }
                m = m.next;
            }
        }
    }

    protected CtMember(CtClass clazz) {
        declaringClass = clazz;
        next = null;
    }

    final CtMember next() { return next; }

    /**
     * This method is invoked when setName() or replaceClassName()
     * in CtClass is called.
     *
     * @see CtMethod#nameReplaced()
     */
    void nameReplaced() {}

    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer(getClass().getName());
        buffer.append("@");
        buffer.append(Integer.toHexString(hashCode()));
        buffer.append("[");
        buffer.append(Modifier.toString(getModifiers()));
        extendToString(buffer);
        buffer.append("]");
        return buffer.toString();
    }

    /**
     * Invoked by {@link #toString()} to add to the buffer and provide the
     * complete value.  Subclasses should invoke this method, adding a
     * space before each token.  The modifiers for the member are
     * provided first; subclasses should provide additional data such
     * as return type, field or method name, etc.
     */
    protected abstract void extendToString(StringBuffer buffer);

    /**
     * Returns the class that declares this member.
     */
    public CtClass getDeclaringClass() { return declaringClass; }

    /**
     * Returns true if this member is accessible from the given class.
     */
    public boolean visibleFrom(CtClass clazz) {<FILL_FUNCTION_BODY>

        int mod = getModifiers();
        if (Modifier.isPublic(mod))
            return true;
        else if (Modifier.isPrivate(mod))
            return clazz == declaringClass;
        else {  // package or protected
            String declName = declaringClass.getPackageName();
            String fromName = clazz.getPackageName();
            boolean visible;
            if (declName == null)
                visible = fromName == null;
            else
                visible = declName.equals(fromName);

            if (!visible && Modifier.isProtected(mod))
                return clazz.subclassOf(declaringClass);

            return visible;
        }
    
<no_super_class>