/*
 * Copyright 1994-2004 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.javac;

import sun.tools.java.*;
import sun.tools.tree.*;
import sun.tools.tree.CompoundStatement;
import sun.tools.asm.Assembler;
import sun.tools.asm.ConstantPool;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.io.IOException;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;

/**
 * This class represents an Java class as it is read from
 * an Java source file.
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 */
@Deprecated
public
class SourceClass extends ClassDefinition {

    /**
     * The toplevel environment, shared with the parser
     */
    Environment toplevelEnv;

    /**
     * The default constructor
     */
    SourceMember defConstructor;

    /**
     * The constant pool
     */
    ConstantPool tab = new ConstantPool();

   /**
     * The list of class dependencies
     */
    Hashtable deps = new Hashtable(11);

    /**
     * The field used to represent "this" in all of my code.
     */
    LocalMember thisArg;

    /**
     * Last token of class, as reported by parser.
     */
    long endPosition;

    /**
     * Access methods for constructors are distinguished from
     * the constructors themselves by a dummy first argument.
     * A unique type used for this purpose and shared by all
     * constructor access methods within a package-member class is
     * maintained here.
     * <p>
     * This field is null except in an outermost class containing
     * one or more classes needing such an access method.
     */
    private Type dummyArgumentType = null;

    /**
     * Constructor
     */
    public SourceClass(Environment env, long where,
                       ClassDeclaration declaration, String documentation,
                       int modifiers, IdentifierToken superClass,
                       IdentifierToken interfaces[],
                       SourceClass outerClass, Identifier localName) {
        super(env.getSource(), where,
              declaration, modifiers, superClass, interfaces);
        setOuterClass(outerClass);

        this.toplevelEnv = env;
        this.documentation = documentation;

        if (ClassDefinition.containsDeprecated(documentation)) {
            this.modifiers |= M_DEPRECATED;
        }

        // Check for a package level class which is declared static.
        if (isStatic() && outerClass == null) {
            env.error(where, "static.class", this);
            this.modifiers &=~ M_STATIC;
        }

        // Inner classes cannot be static, nor can they be interfaces
        // (which are implicitly static).  Static classes and interfaces
        // can only occur as top-level entities.
        //
        // Note that we do not have to check for local classes declared
        // to be static (this is currently caught by the parser) but
        // we check anyway in case the parser is modified to allow this.
        if (isLocal() || (outerClass != null && !outerClass.isTopLevel())) {
            if (isInterface()) {
                env.error(where, "inner.interface");
            } else if (isStatic()) {
                env.error(where, "static.inner.class", this);
                this.modifiers &=~ M_STATIC;
                if (innerClassMember != null) {
                    innerClassMember.subModifiers(M_STATIC);
                }
            }
        }

        if (isPrivate() && outerClass == null) {
            env.error(where, "private.class", this);
            this.modifiers &=~ M_PRIVATE;
        }
        if (isProtected() && outerClass == null) {
            env.error(where, "protected.class", this);
            this.modifiers &=~ M_PROTECTED;
        }
        /*----*
        if ((isPublic() || isProtected()) && isInsideLocal()) {
            env.error(where, "warn.public.local.class", this);
        }
         *----*/

        // maybe define an uplevel "A.this" current instance field
        if (!isTopLevel() && !isLocal()) {
            LocalMember outerArg = ((SourceClass)outerClass).getThisArgument();
            UplevelReference r = getReference(outerArg);
            setOuterMember(r.getLocalField(env));
        }

        // Set simple, unmangled local name for a local or anonymous class.
        // NOTE: It would be OK to do this unconditionally, as null is the
        // correct value for a member (non-local) class.
        if (localName != null)
            setLocalName(localName);

        // Check for inner class with same simple name as one of
        // its enclosing classes.  Note that 'getLocalName' returns
        // the simple, unmangled source-level name of any class.
        // The previous version of this code was not careful to avoid
        // mangled local class names.  This version fixes 4047746.
        Identifier thisName = getLocalName();
        if (thisName != idNull) {
            // Test above suppresses error for nested anonymous classes,
            // which have an internal "name", but are not named in source code.
            for (ClassDefinition scope = outerClass; scope != null;
                  scope = scope.getOuterClass()) {
                Identifier outerName = scope.getLocalName();
                if (thisName.equals(outerName))
                    env.error(where, "inner.redefined", thisName);
            }
        }
    }

    /**
     * Return last position in this class.
     * @see #getWhere
     */
    public long getEndPosition() {
        return endPosition;
    }

    public void setEndPosition(long endPosition) {
        this.endPosition = endPosition;
    }


// JCOV
    /**
     * Return absolute name of source file
     */
    public String getAbsoluteName() {
        String AbsName = ((ClassFile)getSource()).getAbsoluteName();

        return AbsName;
    }
//end JCOV

    /**
     * Return imports
     */
    public Imports getImports() {
        return toplevelEnv.getImports();
    }

    /**
     * Find or create my "this" argument, which is used for all methods.
     */
    public LocalMember getThisArgument() {
        if (thisArg == null) {
            thisArg = new LocalMember(where, this, 0, getType(), idThis);
        }
        return thisArg;
    }

    /**
     * Add a dependency
     */
    public void addDependency(ClassDeclaration c) {
        if (tab != null) {
            tab.put(c);
        }
        // If doing -xdepend option, save away list of class dependencies
        //   making sure to NOT include duplicates or the class we are in
        //   (Hashtable's put() makes sure we don't have duplicates)
        if ( toplevelEnv.print_dependencies() && c != getClassDeclaration() ) {
            deps.put(c,c);
        }
    }

    /**
     * Add a field (check it first)
     */
    public void addMember(Environment env, MemberDefinition f) {
        // Make sure the access permissions are self-consistent:
        switch (f.getModifiers() & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) {
        case M_PUBLIC:
        case M_PRIVATE:
        case M_PROTECTED:
        case 0:
            break;
        default:
            env.error(f.getWhere(), "inconsistent.modifier", f);
            // Cut out the more restrictive modifier(s):
            if (f.isPublic()) {
                f.subModifiers(M_PRIVATE | M_PROTECTED);
            } else {
                f.subModifiers(M_PRIVATE);
            }
            break;
        }

        // Note exemption for synthetic members below.
        if (f.isStatic() && !isTopLevel() && !f.isSynthetic()) {
            if (f.isMethod()) {
                env.error(f.getWhere(), "static.inner.method", f, this);
                f.subModifiers(M_STATIC);
            } else if (f.isVariable()) {
                if (!f.isFinal() || f.isBlankFinal()) {
                    env.error(f.getWhere(), "static.inner.field", f.getName(), this);
                    f.subModifiers(M_STATIC);
                }
                // Even if a static passes this test, there is still another
                // check in 'SourceMember.check'.  The check is delayed so
                // that the initializer may be inspected more closely, using
                // 'isConstant()'.  Part of fix for 4095568.
            } else {
                // Static inner classes are diagnosed in 'SourceClass.<init>'.
                f.subModifiers(M_STATIC);
            }
        }

        if (f.isMethod()) {
            if (f.isConstructor()) {
                if (f.getClassDefinition().isInterface()) {
                    env.error(f.getWhere(), "intf.constructor");
                    return;
                }
                if (f.isNative() || f.isAbstract() ||
                      f.isStatic() || f.isSynchronized() || f.isFinal()) {
                    env.error(f.getWhere(), "constr.modifier", f);
                    f.subModifiers(M_NATIVE | M_ABSTRACT |
                                   M_STATIC | M_SYNCHRONIZED | M_FINAL);
                }
            } else if (f.isInitializer()) {
                if (f.getClassDefinition().isInterface()) {
                    env.error(f.getWhere(), "intf.initializer");
                    return;
                }
            }

            // f is not allowed to return an array of void
            if ((f.getType().getReturnType()).isVoidArray()) {
                env.error(f.getWhere(), "void.array");
            }

            if (f.getClassDefinition().isInterface() &&
                (f.isStatic() || f.isSynchronized() || f.isNative()
                 || f.isFinal() || f.isPrivate() || f.isProtected())) {
                env.error(f.getWhere(), "intf.modifier.method", f);
                f.subModifiers(M_STATIC |  M_SYNCHRONIZED | M_NATIVE |
                               M_FINAL | M_PRIVATE);
            }
            if (f.isTransient()) {
                env.error(f.getWhere(), "transient.meth", f);
                f.subModifiers(M_TRANSIENT);
            }
            if (f.isVolatile()) {
                env.error(f.getWhere(), "volatile.meth", f);
                f.subModifiers(M_VOLATILE);
            }
            if (f.isAbstract()) {
                if (f.isPrivate()) {
                    env.error(f.getWhere(), "abstract.private.modifier", f);
                    f.subModifiers(M_PRIVATE);
                }
                if (f.isStatic()) {
                    env.error(f.getWhere(), "abstract.static.modifier", f);
                    f.subModifiers(M_STATIC);
                }
                if (f.isFinal()) {
                    env.error(f.getWhere(), "abstract.final.modifier", f);
                    f.subModifiers(M_FINAL);
                }
                if (f.isNative()) {
                    env.error(f.getWhere(), "abstract.native.modifier", f);
                    f.subModifiers(M_NATIVE);
                }
                if (f.isSynchronized()) {
                    env.error(f.getWhere(),"abstract.synchronized.modifier",f);
                    f.subModifiers(M_SYNCHRONIZED);
                }
            }
            if (f.isAbstract() || f.isNative()) {
                if (f.getValue() != null) {
                    env.error(f.getWhere(), "invalid.meth.body", f);
                    f.setValue(null);
                }
            } else {
                if (f.getValue() == null) {
                    if (f.isConstructor()) {
                        env.error(f.getWhere(), "no.constructor.body", f);
                    } else {
                        env.error(f.getWhere(), "no.meth.body", f);
                    }
                    f.addModifiers(M_ABSTRACT);
                }
            }
            Vector arguments = f.getArguments();
            if (arguments != null) {
                // arguments can be null if this is an implicit abstract method
                int argumentLength = arguments.size();
                Type argTypes[] = f.getType().getArgumentTypes();
                for (int i = 0; i < argTypes.length; i++) {
                    Object arg = arguments.elementAt(i);
                    long where = f.getWhere();
                    if (arg instanceof MemberDefinition) {
                        where = ((MemberDefinition)arg).getWhere();
                        arg = ((MemberDefinition)arg).getName();
                    }
                    // (arg should be an Identifier now)
                    if (argTypes[i].isType(TC_VOID)
                        || argTypes[i].isVoidArray()) {
                        env.error(where, "void.argument", arg);
                    }
                }
            }
        } else if (f.isInnerClass()) {
            if (f.isVolatile() ||
                f.isTransient() || f.isNative() || f.isSynchronized()) {
                env.error(f.getWhere(), "inner.modifier", f);
                f.subModifiers(M_VOLATILE | M_TRANSIENT |
                               M_NATIVE | M_SYNCHRONIZED);
            }
            // same check as for fields, below:
            if (f.getClassDefinition().isInterface() &&
                  (f.isPrivate() || f.isProtected())) {
                env.error(f.getWhere(), "intf.modifier.field", f);
                f.subModifiers(M_PRIVATE | M_PROTECTED);
                f.addModifiers(M_PUBLIC);
                // Fix up the class itself to agree with
                // the inner-class member.
                ClassDefinition c = f.getInnerClass();
                c.subModifiers(M_PRIVATE | M_PROTECTED);
                c.addModifiers(M_PUBLIC);
            }
        } else {
            if (f.getType().isType(TC_VOID) || f.getType().isVoidArray()) {
                env.error(f.getWhere(), "void.inst.var", f.getName());
                // REMIND: set type to error
                return;
            }

            if (f.isSynchronized() || f.isAbstract() || f.isNative()) {
                env.error(f.getWhere(), "var.modifier", f);
                f.subModifiers(M_SYNCHRONIZED | M_ABSTRACT | M_NATIVE);
            }
            if (f.isStrict()) {
                env.error(f.getWhere(), "var.floatmodifier", f);
                f.subModifiers(M_STRICTFP);
            }
            if (f.isTransient() && isInterface()) {
                env.error(f.getWhere(), "transient.modifier", f);
                f.subModifiers(M_TRANSIENT);
            }
            if (f.isVolatile() && (isInterface() || f.isFinal())) {
                env.error(f.getWhere(), "volatile.modifier", f);
                f.subModifiers(M_VOLATILE);
            }
            if (f.isFinal() && (f.getValue() == null) && isInterface()) {
                env.error(f.getWhere(), "initializer.needed", f);
                f.subModifiers(M_FINAL);
            }

            if (f.getClassDefinition().isInterface() &&
                  (f.isPrivate() || f.isProtected())) {
                env.error(f.getWhere(), "intf.modifier.field", f);
                f.subModifiers(M_PRIVATE | M_PROTECTED);
                f.addModifiers(M_PUBLIC);
            }
        }
        // Do not check for repeated methods here:  Types are not yet resolved.
        if (!f.isInitializer()) {
            for (MemberDefinition f2 = getFirstMatch(f.getName());
                         f2 != null; f2 = f2.getNextMatch()) {
                if (f.isVariable() && f2.isVariable()) {
                    env.error(f.getWhere(), "var.multidef", f, f2);
                    return;
                } else if (f.isInnerClass() && f2.isInnerClass() &&
                           !f.getInnerClass().isLocal() &&
                           !f2.getInnerClass().isLocal()) {
                    // Found a duplicate inner-class member.
                    // Duplicate local classes are detected in
                    // 'VarDeclarationStatement.checkDeclaration'.
                    env.error(f.getWhere(), "inner.class.multidef", f);
                    return;
                }
            }
        }

        super.addMember(env, f);
    }

    /**
     * Create an environment suitable for checking this class.
     * Make sure the source and imports are set right.
     * Make sure the environment contains no context information.
     * (Actually, throw away env altogether and use toplevelEnv instead.)
     */
    public Environment setupEnv(Environment env) {
        // In some cases, we go to some trouble to create the 'env' argument
        // that is discarded.  We should remove the 'env' argument entirely
        // as well as the vestigial code that supports it.  See comments on
        // 'newEnvironment' in 'checkInternal' below.
        return new Environment(toplevelEnv, this);
    }

    /**
     * A source class never reports deprecation, since the compiler
     * allows access to deprecated features that are being compiled
     * in the same job.
     */
    public boolean reportDeprecated(Environment env) {
        return false;
    }

    /**
     * See if the source file of this class is right.
     * @see ClassDefinition#noteUsedBy
     */
    public void noteUsedBy(ClassDefinition ref, long where, Environment env) {
        // If this class is not public, watch for cross-file references.
        super.noteUsedBy(ref, where, env);
        ClassDefinition def = this;
        while (def.isInnerClass()) {
            def = def.getOuterClass();
        }
        if (def.isPublic()) {
            return;             // already checked
        }
        while (ref.isInnerClass()) {
            ref = ref.getOuterClass();
        }
        if (def.getSource().equals(ref.getSource())) {
            return;             // intra-file reference
        }
        ((SourceClass)def).checkSourceFile(env, where);
    }

    /**
     * Check this class and all its fields.
     */
    public void check(Environment env) throws ClassNotFound {
        if (tracing) env.dtEnter("SourceClass.check: " + getName());
        if (isInsideLocal()) {
            // An inaccessible class gets checked when the surrounding
            // block is checked.
            // QUERY: Should this case ever occur?
            // What would invoke checking of a local class aside from
            // checking the surrounding method body?
            if (tracing) env.dtEvent("SourceClass.check: INSIDE LOCAL " +
                                     getOuterClass().getName());
            getOuterClass().check(env);
        } else {
            if (isInnerClass()) {
                if (tracing) env.dtEvent("SourceClass.check: INNER CLASS " +
                                         getOuterClass().getName());
                // Make sure the outer is checked first.
                ((SourceClass)getOuterClass()).maybeCheck(env);
            }
            Vset vset = new Vset();
            Context ctx = null;
            if (tracing)
                env.dtEvent("SourceClass.check: CHECK INTERNAL " + getName());
            vset = checkInternal(setupEnv(env), ctx, vset);
            // drop vset here
        }
        if (tracing) env.dtExit("SourceClass.check: " + getName());
    }

    private void maybeCheck(Environment env) throws ClassNotFound {
        if (tracing) env.dtEvent("SourceClass.maybeCheck: " + getName());
        // Check this class now, if it has not yet been checked.
        // Cf. Main.compile().  Perhaps this code belongs there somehow.
        ClassDeclaration c = getClassDeclaration();
        if (c.getStatus() == CS_PARSED) {
            // Set it first to avoid vicious circularity:
            c.setDefinition(this, CS_CHECKED);
            check(env);
        }
    }

    private Vset checkInternal(Environment env, Context ctx, Vset vset)
                throws ClassNotFound {
        Identifier nm = getClassDeclaration().getName();
        if (env.verbose()) {
            env.output("[checking class " + nm + "]");
        }

        // Save context enclosing class for later access
        // by 'ClassDefinition.resolveName.'
        classContext = ctx;

        // At present, the call to 'newEnvironment' is not needed.
        // The incoming environment to 'basicCheck' is always passed to
        // 'setupEnv', which discards it completely.  This is also the
        // only call to 'newEnvironment', which is now apparently dead code.
        basicCheck(Context.newEnvironment(env, ctx));

        // Validate access for all inner-class components
        // of a qualified name, not just the last one, which
        // is checked below.  Yes, this is a dirty hack...
        // Much of this code was cribbed from 'checkSupers'.
        // Part of fix for 4094658.
        ClassDeclaration sup = getSuperClass();
        if (sup != null) {
            long where = getWhere();
            where = IdentifierToken.getWhere(superClassId, where);
            env.resolveExtendsByName(where, this, sup.getName());
        }
        for (int i = 0 ; i < interfaces.length ; i++) {
            ClassDeclaration intf = interfaces[i];
            long where = getWhere();
            // Error localization fails here if interfaces were
            // elided during error recovery from an invalid one.
            if (interfaceIds != null
                && interfaceIds.length == interfaces.length) {
                where = IdentifierToken.getWhere(interfaceIds[i], where);
            }
            env.resolveExtendsByName(where, this, intf.getName());
        }

        // Does the name already exist in an imported package?
        // See JLS 8.1 for the precise rules.
        if (!isInnerClass() && !isInsideLocal()) {
            // Discard package qualification for the import checks.
            Identifier simpleName = nm.getName();
            try {
                // We want this to throw a ClassNotFound exception
                Imports imports = toplevelEnv.getImports();
                Identifier ID = imports.resolve(env, simpleName);
                if (ID != getName())
                    env.error(where, "class.multidef.import", simpleName, ID);
            } catch (AmbiguousClass e) {
                // At least one of e.name1 and e.name2 must be different
                Identifier ID = (e.name1 != getName()) ? e.name1 : e.name2;
                env.error(where, "class.multidef.import", simpleName, ID);
            }  catch (ClassNotFound e) {
                // we want this to happen
            }

            // Make sure that no package with the same fully qualified
            // name exists.  This is required by JLS 7.1.  We only need
            // to perform this check for top level classes -- it isn't
            // necessary for inner classes.  (bug 4101529)
            //
            // This change has been backed out because, on WIN32, it
            // failed to distinguish between java.awt.event and
            // java.awt.Event when looking for a directory.  We will
            // add this back in later.
            //
            // try {
            //  if (env.getPackage(nm).exists()) {
            //      env.error(where, "class.package.conflict", nm);
            //  }
            // } catch (java.io.IOException ee) {
            //  env.error(where, "io.exception.package", nm);
            // }

            // Make sure it was defined in the right file
            if (isPublic()) {
                checkSourceFile(env, getWhere());
            }
        }

        vset = checkMembers(env, ctx, vset);
        return vset;
    }

    private boolean sourceFileChecked = false;

    /**
     * See if the source file of this class is of the right name.
     */
    public void checkSourceFile(Environment env, long where) {
        // one error per offending class is sufficient
        if (sourceFileChecked)  return;
        sourceFileChecked = true;

        String fname = getName().getName() + ".java";
        String src = ((ClassFile)getSource()).getName();
        if (!src.equals(fname)) {
            if (isPublic()) {
                env.error(where, "public.class.file", this, fname);
            } else {
                env.error(where, "warn.package.class.file", this, src, fname);
            }
        }
    }

    // Set true if superclass (but not necessarily superinterfaces) have
    // been checked.  If the superclass is still unresolved, then an error
    // message should have been issued, and we assume that no further
    // resolution is possible.
    private boolean supersChecked = false;

    /**
     * Overrides 'ClassDefinition.getSuperClass'.
     */

    public ClassDeclaration getSuperClass(Environment env) {
        if (tracing) env.dtEnter("SourceClass.getSuperClass: " + this);
        // Superclass may fail to be set because of error recovery,
        // so resolve types here only if 'checkSupers' has not yet
        // completed its checks on the superclass.
        // QUERY: Can we eliminate the need to resolve superclasses on demand?
        // See comments in 'checkSupers' and in 'ClassDefinition.getInnerClass'.
        if (superClass == null && superClassId != null && !supersChecked) {
            resolveTypeStructure(env);
            // We used to report an error here if the superclass was not
            // resolved.  Having moved the call to 'checkSupers' from 'basicCheck'
            // into 'resolveTypeStructure', the errors reported here should have
            // already been reported.  Furthermore, error recovery can null out
            // the superclass, which would cause a spurious error from the test here.
        }
        if (tracing) env.dtExit("SourceClass.getSuperClass: " + this);
        return superClass;
    }

    /**
     * Check that all superclasses and superinterfaces are defined and
     * well formed.  Among other checks, verify that the inheritance
     * graph is acyclic.  Called from 'resolveTypeStructure'.
     */

    private void checkSupers(Environment env) throws ClassNotFound {

        // *** DEBUG ***
        supersCheckStarted = true;

        if (tracing) env.dtEnter("SourceClass.checkSupers: " + this);

        if (isInterface()) {
            if (isFinal()) {
                Identifier nm = getClassDeclaration().getName();
                env.error(getWhere(), "final.intf", nm);
                // Interfaces have no superclass.  Superinterfaces
                // are checked below, in code shared with the class case.
            }
        } else {
            // Check superclass.
            // Call to 'getSuperClass(env)' (note argument) attempts
            // 'resolveTypeStructure' if superclass has not successfully
            // been resolved.  Since we have just now called 'resolveSupers'
            // (see our call in 'resolveTypeStructure'), it is not clear
            // that this can do any good.  Why not 'getSuperClass()' here?
            if (getSuperClass(env) != null) {
                long where = getWhere();
                where = IdentifierToken.getWhere(superClassId, where);
                try {
                    ClassDefinition def =
                        getSuperClass().getClassDefinition(env);
                    // Resolve superclass and its ancestors.
                    def.resolveTypeStructure(env);
                    // Access to the superclass should be checked relative
                    // to the surrounding context, not as if the reference
                    // appeared within the class body. Changed 'canAccess'
                    // to 'extendsCanAccess' to fix 4087314.
                    if (!extendsCanAccess(env, getSuperClass())) {
                        env.error(where, "cant.access.class", getSuperClass());
                        // Might it be a better recovery to let the access go through?
                        superClass = null;
                    } else if (def.isFinal()) {
                        env.error(where, "super.is.final", getSuperClass());
                        // Might it be a better recovery to let the access go through?
                        superClass = null;
                    } else if (def.isInterface()) {
                        env.error(where, "super.is.intf", getSuperClass());
                        superClass = null;
                    } else if (superClassOf(env, getSuperClass())) {
                        env.error(where, "cyclic.super");
                        superClass = null;
                    } else {
                        def.noteUsedBy(this, where, env);
                    }
                    if (superClass == null) {
                        def = null;
                    } else {
                        // If we have a valid superclass, check its
                        // supers as well, and so on up to root class.
                        // Call to 'enclosingClassOf' will raise
                        // 'NullPointerException' if 'def' is null,
                        // so omit this check as error recovery.
                        ClassDefinition sup = def;
                        for (;;) {
                            if (enclosingClassOf(sup)) {
                                // Do we need a similar test for
                                // interfaces?  See bugid 4038529.
                                env.error(where, "super.is.inner");
                                superClass = null;
                                break;
                            }
                            // Since we resolved the superclass and its
                            // ancestors above, we should not discover
                            // any unresolved classes on the superclass
                            // chain.  It should thus be sufficient to
                            // call 'getSuperClass()' (no argument) here.
                            ClassDeclaration s = sup.getSuperClass(env);
                            if (s == null) {
                                // Superclass not resolved due to error.
                                break;
                            }
                            sup = s.getClassDefinition(env);
                        }
                    }
                } catch (ClassNotFound e) {
                    // Error is detected in call to 'getClassDefinition'.
                    // The class may actually exist but be ambiguous.
                    // Call env.resolve(e.name) to see if it is.
                    // env.resolve(name) will definitely tell us if the
                    // class is ambiguous, but may not necessarily tell
                    // us if the class is not found.
                    // (part of solution for 4059855)
                reportError: {
                        try {
                            env.resolve(e.name);
                        } catch (AmbiguousClass ee) {
                            env.error(where,
                                      "ambig.class", ee.name1, ee.name2);
                            superClass = null;
                            break reportError;
                        } catch (ClassNotFound ee) {
                            // fall through
                        }
                        env.error(where, "super.not.found", e.name, this);
                        superClass = null;
                    } // The break exits this block
                }

            } else {
                // Superclass was null on entry, after call to
                // 'resolveSupers'.  This should normally not happen,
                // as 'resolveSupers' sets 'superClass' to a non-null
                // value for all named classes, except for one special
                // case: 'java.lang.Object', which has no superclass.
                if (isAnonymous()) {
                    // checker should have filled it in first
                    throw new CompilerError("anonymous super");
                } else  if (!getName().equals(idJavaLangObject)) {
                    throw new CompilerError("unresolved super");
                }
            }
        }

        // At this point, if 'superClass' is null due to an error
        // in the user program, a message should have been issued.
        supersChecked = true;

        // Check interfaces
        for (int i = 0 ; i < interfaces.length ; i++) {
            ClassDeclaration intf = interfaces[i];
            long where = getWhere();
            if (interfaceIds != null
                && interfaceIds.length == interfaces.length) {
                where = IdentifierToken.getWhere(interfaceIds[i], where);
            }
            try {
                ClassDefinition def = intf.getClassDefinition(env);
                // Resolve superinterface and its ancestors.
                def.resolveTypeStructure(env);
                // Check superinterface access in the correct context.
                // Changed 'canAccess' to 'extendsCanAccess' to fix 4087314.
                if (!extendsCanAccess(env, intf)) {
                    env.error(where, "cant.access.class", intf);
                } else if (!intf.getClassDefinition(env).isInterface()) {
                    env.error(where, "not.intf", intf);
                } else if (isInterface() && implementedBy(env, intf)) {
                    env.error(where, "cyclic.intf", intf);
                } else {
                    def.noteUsedBy(this, where, env);
                    // Interface is OK, leave it in the interface list.
                    continue;
                }
            } catch (ClassNotFound e) {
                // The interface may actually exist but be ambiguous.
                // Call env.resolve(e.name) to see if it is.
                // env.resolve(name) will definitely tell us if the
                // interface is ambiguous, but may not necessarily tell
                // us if the interface is not found.
                // (part of solution for 4059855)
            reportError2: {
                    try {
                        env.resolve(e.name);
                    } catch (AmbiguousClass ee) {
                        env.error(where,
                                  "ambig.class", ee.name1, ee.name2);
                        superClass = null;
                        break reportError2;
                    } catch (ClassNotFound ee) {
                        // fall through
                    }
                    env.error(where, "intf.not.found", e.name, this);
                    superClass = null;
                } // The break exits this block
            }
            // Remove this interface from the list of interfaces
            // as recovery from an error.
            ClassDeclaration newInterfaces[] =
                new ClassDeclaration[interfaces.length - 1];
            System.arraycopy(interfaces, 0, newInterfaces, 0, i);
            System.arraycopy(interfaces, i + 1, newInterfaces, i,
                             newInterfaces.length - i);
            interfaces = newInterfaces;
            --i;
        }
        if (tracing) env.dtExit("SourceClass.checkSupers: " + this);
    }

    /**
     * Check all of the members of this class.
     * <p>
     * Inner classes are checked in the following way.  Any class which
     * is immediately contained in a block (anonymous and local classes)
     * is checked along with its containing method; see the
     * SourceMember.check() method for more information.  Member classes
     * of this class are checked immediately after this class, unless this
     * class is insideLocal(), in which case, they are checked with the
     * rest of the members.
     */
    private Vset checkMembers(Environment env, Context ctx, Vset vset)
            throws ClassNotFound {

        // bail out if there were any errors
        if (getError()) {
            return vset;
        }

        // Make sure that all of our member classes have been
        // basicCheck'ed before we check the rest of our members.
        // If our member classes haven't been basicCheck'ed, then they
        // may not have <init> methods.  It is important that they
        // have <init> methods so we can process NewInstanceExpressions
        // correctly.  This problem didn't occur before 1.2beta1.
        // This is a fix for bug 4082816.
        for (MemberDefinition f = getFirstMember();
                     f != null; f = f.getNextMember()) {
            if (f.isInnerClass()) {
                // System.out.println("Considering " + f + " in " + this);
                SourceClass cdef = (SourceClass) f.getInnerClass();
                if (cdef.isMember()) {
                    cdef.basicCheck(env);
                }
            }
        }

        if (isFinal() && isAbstract()) {
            env.error(where, "final.abstract", this.getName().getName());
        }

        // This class should be abstract if there are any abstract methods
        // in our parent classes and interfaces which we do not override.
        // There are odd cases when, even though we cannot access some
        // abstract method from our superclass, that abstract method can
        // still force this class to be abstract.  See the discussion in
        // bug id 1240831.
        if (!isInterface() && !isAbstract() && mustBeAbstract(env)) {
            // Set the class abstract.
            modifiers |= M_ABSTRACT;

            // Tell the user which methods force this class to be abstract.

            // First list all of the "unimplementable" abstract methods.
            Iterator iter = getPermanentlyAbstractMethods();
            while (iter.hasNext()) {
                MemberDefinition method = (MemberDefinition) iter.next();
                // We couldn't override this method even if we
                // wanted to.  Try to make the error message
                // as non-confusing as possible.
                env.error(where, "abstract.class.cannot.override",
                          getClassDeclaration(), method,
                          method.getDefiningClassDeclaration());
            }

            // Now list all of the traditional abstract methods.
            iter = getMethods(env);
            while (iter.hasNext()) {
                // For each method, check if it is abstract.  If it is,
                // output an appropriate error message.
                MemberDefinition method = (MemberDefinition) iter.next();
                if (method.isAbstract()) {
                    env.error(where, "abstract.class",
                              getClassDeclaration(), method,
                              method.getDefiningClassDeclaration());
                }
            }
        }

        // Check the instance variables in a pre-pass before any constructors.
        // This lets constructors "in-line" any initializers directly.
        // It also lets us do some definite assignment checks on variables.
        Context ctxInit = new Context(ctx);
        Vset vsInst = vset.copy();
        Vset vsClass = vset.copy();

        // Do definite assignment checking on blank finals.
        // Other variables do not need such checks.  The simple textual
        // ordering constraints implemented by MemberDefinition.canReach()
        // are necessary and sufficient for the other variables.
        // Note that within non-static code, all statics are always
        // definitely assigned, and vice-versa.
        for (MemberDefinition f = getFirstMember();
                     f != null; f = f.getNextMember()) {
            if (f.isVariable() && f.isBlankFinal()) {
                // The following allocates a LocalMember object as a proxy
                // to represent the field.
                int number = ctxInit.declareFieldNumber(f);
                if (f.isStatic()) {
                    vsClass = vsClass.addVarUnassigned(number);
                    vsInst = vsInst.addVar(number);
                } else {
                    vsInst = vsInst.addVarUnassigned(number);
                    vsClass = vsClass.addVar(number);
                }
            }
        }

        // For instance variable checks, use a context with a "this" parameter.
        Context ctxInst = new Context(ctxInit, this);
        LocalMember thisArg = getThisArgument();
        int thisNumber = ctxInst.declare(env, thisArg);
        vsInst = vsInst.addVar(thisNumber);

        // Do all the initializers in order, checking the definite
        // assignment of blank finals.  Separate static from non-static.
        for (MemberDefinition f = getFirstMember();
                     f != null; f = f.getNextMember()) {
            try {
                if (f.isVariable() || f.isInitializer()) {
                    if (f.isStatic()) {
                        vsClass = f.check(env, ctxInit, vsClass);
                    } else {
                        vsInst = f.check(env, ctxInst, vsInst);
                    }
                }
            } catch (ClassNotFound ee) {
                env.error(f.getWhere(), "class.not.found", ee.name, this);
            }
        }

        checkBlankFinals(env, ctxInit, vsClass, true);

        // Check the rest of the field definitions.
        // (Note:  Re-checking a field is a no-op.)
        for (MemberDefinition f = getFirstMember();
                     f != null; f = f.getNextMember()) {
            try {
                if (f.isConstructor()) {
                    // When checking a constructor, an explicit call to
                    // 'this(...)' makes all blank finals definitely assigned.
                    // See 'MethodExpression.checkValue'.
                    Vset vsCon = f.check(env, ctxInit, vsInst.copy());
                    // May issue multiple messages for the same variable!!
                    checkBlankFinals(env, ctxInit, vsCon, false);
                    // (drop vsCon here)
                } else {
                    Vset vsFld = f.check(env, ctx, vset.copy());
                    // (drop vsFld here)
                }
            } catch (ClassNotFound ee) {
                env.error(f.getWhere(), "class.not.found", ee.name, this);
            }
        }

        // Must mark class as checked before visiting inner classes,
        // as they may in turn request checking of the current class
        // as an outer class.  Fix for bug id 4056774.
        getClassDeclaration().setDefinition(this, CS_CHECKED);

        // Also check other classes in the same nest.
        // All checking of this nest must be finished before any
        // of its classes emit bytecode.
        // Otherwise, the inner classes might not have a chance to
        // add access or class literal fields to the outer class.
        for (MemberDefinition f = getFirstMember();
                     f != null; f = f.getNextMember()) {
            if (f.isInnerClass()) {
                SourceClass cdef = (SourceClass) f.getInnerClass();
                if (!cdef.isInsideLocal()) {
                    cdef.maybeCheck(env);
                }
            }
        }

        // Note:  Since inner classes cannot set up-level variables,
        // the returned vset is always equal to the passed-in vset.
        // Still, we'll return it for the sake of regularity.
        return vset;
    }

    /** Make sure all my blank finals exist now. */

    private void checkBlankFinals(Environment env, Context ctxInit, Vset vset,
                                  boolean isStatic) {
        for (int i = 0; i < ctxInit.getVarNumber(); i++) {
            if (!vset.testVar(i)) {
                MemberDefinition ff = ctxInit.getElement(i);
                if (ff != null && ff.isBlankFinal()
                    && ff.isStatic() == isStatic
                    && ff.getClassDefinition() == this) {
                    env.error(ff.getWhere(),
                              "final.var.not.initialized", ff.getName());
                }
            }
        }
    }

    /**
     * Check this class has its superclass and its interfaces.  Also
     * force it to have an <init> method (if it doesn't already have one)
     * and to have all the abstract methods of its parents.
     */
    private boolean basicChecking = false;
    private boolean basicCheckDone = false;
    protected void basicCheck(Environment env) throws ClassNotFound {

        if (tracing) env.dtEnter("SourceClass.basicCheck: " + getName());

        super.basicCheck(env);

        if (basicChecking || basicCheckDone) {
            if (tracing) env.dtExit("SourceClass.basicCheck: OK " + getName());
            return;
        }

        if (tracing) env.dtEvent("SourceClass.basicCheck: CHECKING " + getName());

        basicChecking = true;

        env = setupEnv(env);

        Imports imports = env.getImports();
        if (imports != null) {
            imports.resolve(env);
        }

        resolveTypeStructure(env);

        // Check the existence of the superclass and all interfaces.
        // Also responsible for breaking inheritance cycles.  This call
        // has been moved to 'resolveTypeStructure', just after the call
        // to 'resolveSupers', as inheritance cycles must be broken before
        // resolving types within the members.  Fixes 4073739.
        //   checkSupers(env);

        if (!isInterface()) {

            // Add implicit <init> method, if necessary.
            // QUERY:  What keeps us from adding an implicit constructor
            // when the user explicitly declares one?  Is it truly guaranteed
            // that the declaration for such an explicit constructor will have
            // been processed by the time we arrive here?  In general, 'basicCheck'
            // is called very early, prior to the normal member checking phase.
            if (!hasConstructor()) {
                Node code = new CompoundStatement(getWhere(), new Statement[0]);
                Type t = Type.tMethod(Type.tVoid);

                // Default constructors inherit the access modifiers of their
                // class.  For non-inner classes, this follows from JLS 8.6.7,
                // as the only possible modifier is 'public'.  For the sake of
                // robustness in the presence of errors, we ignore any other
                // modifiers.  For inner classes, the rule needs to be extended
                // in some way to account for the possibility of private and
                // protected classes.  We make the 'obvious' extension, however,
                // the inner classes spec is silent on this issue, and a definitive
                // resolution is needed.  See bugid 4087421.
                // WORKAROUND: A private constructor might need an access method,
                // but it is not possible to create one due to a restriction in
                // the verifier.  (This is a known problem -- see 4015397.)
                // We therefore do not inherit the 'private' modifier from the class,
                // allowing the default constructor to be package private.  This
                // workaround can be observed via reflection, but is otherwise
                // undetectable, as the constructor is always accessible within
                // the class in which its containing (private) class appears.
                int accessModifiers = getModifiers() &
                    (isInnerClass() ? (M_PUBLIC | M_PROTECTED) : M_PUBLIC);
                env.makeMemberDefinition(env, getWhere(), this, null,
                                         accessModifiers,
                                         t, idInit, null, null, code);
            }
        }

        // Only do the inheritance/override checks if they are turned on.
        // The idea here is that they will be done in javac, but not
        // in javadoc.  See the comment for turnOffChecks(), above.
        if (doInheritanceChecks) {

            // Verify the compatibility of all inherited method definitions
            // by collecting all of our inheritable methods.
            collectInheritedMethods(env);
        }

        basicChecking = false;
        basicCheckDone = true;
        if (tracing) env.dtExit("SourceClass.basicCheck: " + getName());
    }

    /**
     * Add a group of methods to this class as miranda methods.
     *
     * For a definition of Miranda methods, see the comment above the
     * method addMirandaMethods() in the file
     * sun/tools/java/ClassDeclaration.java
     */
    protected void addMirandaMethods(Environment env,
                                     Iterator mirandas) {

        while(mirandas.hasNext()) {
            MemberDefinition method =
                (MemberDefinition)mirandas.next();

            addMember(method);

            //System.out.println("adding miranda method " + newMethod +
            //                   " to " + this);
        }
    }

    /**
     * <em>After parsing is complete</em>, resolve all names
     * except those inside method bodies or initializers.
     * In particular, this is the point at which we find out what
     * kinds of variables and methods there are in the classes,
     * and therefore what is each class's interface to the world.
     * <p>
     * Also perform certain other transformations, such as inserting
     * "this$C" arguments into constructors, and reorganizing structure
     * to flatten qualified member names.
     * <p>
     * Do not perform type-based or name-based consistency checks
     * or normalizations (such as default nullary constructors),
     * and do not attempt to compile code against this class,
     * until after this phase.
     */

    private boolean resolving = false;

    public void resolveTypeStructure(Environment env) {

        if (tracing)
            env.dtEnter("SourceClass.resolveTypeStructure: " + getName());

        // Resolve immediately enclosing type, which in turn
        // forces resolution of all enclosing type declarations.
        ClassDefinition oc = getOuterClass();
        if (oc != null && oc instanceof SourceClass
            && !((SourceClass)oc).resolved) {
            // Do the outer class first, always.
            ((SourceClass)oc).resolveTypeStructure(env);
            // (Note:  this.resolved is probably true at this point.)
        }

        // Punt if we've already resolved this class, or are currently
        // in the process of doing so.
        if (resolved || resolving) {
            if (tracing)
                env.dtExit("SourceClass.resolveTypeStructure: OK " + getName());
            return;
        }

        // Previously, 'resolved' was set here, and served to prevent
        // duplicate resolutions here as well as its function in
        // 'ClassDefinition.addMember'.  Now, 'resolving' serves the
        // former purpose, distinct from that of 'resolved'.
        resolving = true;

        if (tracing)
            env.dtEvent("SourceClass.resolveTypeStructure: RESOLVING " + getName());

        env = setupEnv(env);

        // Resolve superclass names to class declarations
        // for the immediate superclass and superinterfaces.
        resolveSupers(env);

        // Check all ancestor superclasses for various
        // errors, verifying definition of all superclasses
        // and superinterfaces.  Also breaks inheritance cycles.
        // Calls 'resolveTypeStructure' recursively for ancestors
        // This call used to appear in 'basicCheck', but was not
        // performed early enough.  Most of the compiler will barf
        // on inheritance cycles!
        try {
            checkSupers(env);
        } catch (ClassNotFound ee) {
            // Undefined classes should be reported by 'checkSupers'.
            env.error(where, "class.not.found", ee.name, this);
        }

        for (MemberDefinition
                 f = getFirstMember() ; f != null ; f = f.getNextMember()) {
            if (f instanceof SourceMember)
                ((SourceMember)f).resolveTypeStructure(env);
        }

        resolving = false;

        // Mark class as resolved.  If new members are subsequently
        // added to the class, they will be resolved at that time.
        // See 'ClassDefinition.addMember'.  Previously, this variable was
        // set prior to the calls to 'checkSupers' and 'resolveTypeStructure'
        // (which may engender further calls to 'checkSupers').  This could
        // lead to duplicate resolution of implicit constructors, as the call to
        // 'basicCheck' from 'checkSupers' could add the constructor while
        // its class is marked resolved, and thus would resolve the constructor,
        // believing it to be a "late addition".  It would then be resolved
        // redundantly during the normal traversal of the members, which
        // immediately follows in the code above.
        resolved = true;

        // Now we have enough information to detect method repeats.
        for (MemberDefinition
                 f = getFirstMember() ; f != null ; f = f.getNextMember()) {
            if (f.isInitializer())  continue;
            if (!f.isMethod())  continue;
            for (MemberDefinition f2 = f; (f2 = f2.getNextMatch()) != null; ) {
                if (!f2.isMethod())  continue;
                if (f.getType().equals(f2.getType())) {
                    env.error(f.getWhere(), "meth.multidef", f);
                    continue;
                }
                if (f.getType().equalArguments(f2.getType())) {
                    env.error(f.getWhere(), "meth.redef.rettype", f, f2);
                    continue;
                }
            }
        }
        if (tracing)
            env.dtExit("SourceClass.resolveTypeStructure: " + getName());
    }

    protected void resolveSupers(Environment env) {
        if (tracing)
            env.dtEnter("SourceClass.resolveSupers: " + this);
        // Find the super class
        if (superClassId != null && superClass == null) {
            superClass = resolveSuper(env, superClassId);
            // Special-case java.lang.Object here (not in the parser).
            // In all other cases, if we have a valid 'superClassId',
            // we return with a valid and non-null 'superClass' value.
            if (superClass == getClassDeclaration()
                && getName().equals(idJavaLangObject)) {
                    superClass = null;
                    superClassId = null;
            }
        }
        // Find interfaces
        if (interfaceIds != null && interfaces == null) {
            interfaces = new ClassDeclaration[interfaceIds.length];
            for (int i = 0 ; i < interfaces.length ; i++) {
                interfaces[i] = resolveSuper(env, interfaceIds[i]);
                for (int j = 0; j < i; j++) {
                    if (interfaces[i] == interfaces[j]) {
                        Identifier id = interfaceIds[i].getName();
                        long where = interfaceIds[j].getWhere();
                        env.error(where, "intf.repeated", id);
                    }
                }
            }
        }
        if (tracing)
            env.dtExit("SourceClass.resolveSupers: " + this);
    }

    private ClassDeclaration resolveSuper(Environment env, IdentifierToken t) {
        Identifier name = t.getName();
        if (tracing)
            env.dtEnter("SourceClass.resolveSuper: " + name);
        if (isInnerClass())
            name = outerClass.resolveName(env, name);
        else
            name = env.resolveName(name);
        ClassDeclaration result = env.getClassDeclaration(name);
        // Result is never null, as a new 'ClassDeclaration' is
        // created if one with the given name does not exist.
        if (tracing) env.dtExit("SourceClass.resolveSuper: " + name);
        return result;
    }

    /**
     * During the type-checking of an outer method body or initializer,
     * this routine is called to check a local class body
     * in the proper context.
     * @param   sup     the named super class or interface (if anonymous)
     * @param   args    the actual arguments (if anonymous)
     */
    public Vset checkLocalClass(Environment env, Context ctx, Vset vset,
                                ClassDefinition sup,
                                Expression args[], Type argTypes[]
                                ) throws ClassNotFound {
        env = setupEnv(env);

        if ((sup != null) != isAnonymous()) {
            throw new CompilerError("resolveAnonymousStructure");
        }
        if (isAnonymous()) {
            resolveAnonymousStructure(env, sup, args, argTypes);
        }

        // Run the checks in the lexical context from the outer class.
        vset = checkInternal(env, ctx, vset);

        // This is now done by 'checkInternal' via its call to 'checkMembers'.
        // getClassDeclaration().setDefinition(this, CS_CHECKED);

        return vset;
    }

    /**
     * As with checkLocalClass, run the inline phase for a local class.
     */
    public void inlineLocalClass(Environment env) {
        for (MemberDefinition
                 f = getFirstMember(); f != null; f = f.getNextMember()) {
            if ((f.isVariable() || f.isInitializer()) && !f.isStatic()) {
                continue;       // inlined inside of constructors only
            }
            try {
                ((SourceMember)f).inline(env);
            } catch (ClassNotFound ee) {
                env.error(f.getWhere(), "class.not.found", ee.name, this);
            }
        }
        if (getReferencesFrozen() != null && !inlinedLocalClass) {
            inlinedLocalClass = true;
            // add more constructor arguments for uplevel references
            for (MemberDefinition
                     f = getFirstMember(); f != null; f = f.getNextMember()) {
                if (f.isConstructor()) {
                    //((SourceMember)f).addUplevelArguments(false);
                    ((SourceMember)f).addUplevelArguments();
                }
            }
        }
    }
    private boolean inlinedLocalClass = false;

    /**
     * Check a class which is inside a local class, but is not itself local.
     */
    public Vset checkInsideClass(Environment env, Context ctx, Vset vset)
                throws ClassNotFound {
        if (!isInsideLocal() || isLocal()) {
            throw new CompilerError("checkInsideClass");
        }
        return checkInternal(env, ctx, vset);
    }

    /**
     * Just before checking an anonymous class, decide its true
     * inheritance, and build its (sole, implicit) constructor.
     */
    private void resolveAnonymousStructure(Environment env,
                                           ClassDefinition sup,
                                           Expression args[], Type argTypes[]
                                           ) throws ClassNotFound {

        if (tracing) env.dtEvent("SourceClass.resolveAnonymousStructure: " +
                                 this + ", super " + sup);

        // Decide now on the superclass.

        // This check has been removed as part of the fix for 4055017.
        // In the anonymous class created to hold the 'class$' method
        // of an interface, 'superClassId' refers to 'java.lang.Object'.
        /*---------------------*
        if (!(superClass == null && superClassId.getName() == idNull)) {
            throw new CompilerError("superclass "+superClass);
        }
        *---------------------*/

        if (sup.isInterface()) {
            // allow an interface in the "super class" position
            int ni = (interfaces == null) ? 0 : interfaces.length;
            ClassDeclaration i1[] = new ClassDeclaration[1+ni];
            if (ni > 0) {
                System.arraycopy(interfaces, 0, i1, 1, ni);
                if (interfaceIds != null && interfaceIds.length == ni) {
                    IdentifierToken id1[] = new IdentifierToken[1+ni];
                    System.arraycopy(interfaceIds, 0, id1, 1, ni);
                    id1[0] = new IdentifierToken(sup.getName());
                }
            }
            i1[0] = sup.getClassDeclaration();
            interfaces = i1;

            sup = toplevelEnv.getClassDefinition(idJavaLangObject);
        }
        superClass = sup.getClassDeclaration();

        if (hasConstructor()) {
            throw new CompilerError("anonymous constructor");
        }

        // Synthesize an appropriate constructor.
        Type t = Type.tMethod(Type.tVoid, argTypes);
        IdentifierToken names[] = new IdentifierToken[argTypes.length];
        for (int i = 0; i < names.length; i++) {
            names[i] = new IdentifierToken(args[i].getWhere(),
                                           Identifier.lookup("$"+i));
        }
        int outerArg = (sup.isTopLevel() || sup.isLocal()) ? 0 : 1;
        Expression superArgs[] = new Expression[-outerArg + args.length];
        for (int i = outerArg ; i < args.length ; i++) {
            superArgs[-outerArg + i] = new IdentifierExpression(names[i]);
        }
        long where = getWhere();
        Expression superExp;
        if (outerArg == 0) {
            superExp = new SuperExpression(where);
        } else {
            superExp = new SuperExpression(where,
                                           new IdentifierExpression(names[0]));
        }
        Expression superCall = new MethodExpression(where,
                                                    superExp, idInit,
                                                    superArgs);
        Statement body[] = { new ExpressionStatement(where, superCall) };
        Node code = new CompoundStatement(where, body);
        int mod = M_SYNTHETIC; // ISSUE: make M_PRIVATE, with wrapper?
        env.makeMemberDefinition(env, where, this, null,
                                mod, t, idInit, names, null, code);
    }

    /**
     * Convert class modifiers to a string for diagnostic purposes.
     * Accepts modifiers applicable to inner classes and that appear
     * in the InnerClasses attribute only, as well as those that may
     * appear in the class modifier proper.
     */

    private static int classModifierBits[] =
        { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
          ACC_INTERFACE, ACC_ABSTRACT, ACC_SUPER, M_ANONYMOUS, M_LOCAL,
          M_STRICTFP, ACC_STRICT};

    private static String classModifierNames[] =
        { "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL",
          "INTERFACE", "ABSTRACT", "SUPER", "ANONYMOUS", "LOCAL",
          "STRICTFP", "STRICT"};

    static String classModifierString(int mods) {
        String s = "";
        for (int i = 0; i < classModifierBits.length; i++) {
            if ((mods & classModifierBits[i]) != 0) {
                s = s + " " + classModifierNames[i];
                mods &= ~classModifierBits[i];
            }
        }
        if (mods != 0) {
            s = s + " ILLEGAL:" + Integer.toHexString(mods);
        }
        return s;
    }

    /**
     * Find or create an access method for a private member,
     * or return null if this is not possible.
     */
    public MemberDefinition getAccessMember(Environment env, Context ctx,
                                          MemberDefinition field, boolean isSuper) {
        return getAccessMember(env, ctx, field, false, isSuper);
    }

    public MemberDefinition getUpdateMember(Environment env, Context ctx,
                                          MemberDefinition field, boolean isSuper) {
        if (!field.isVariable()) {
            throw new CompilerError("method");
        }
        return getAccessMember(env, ctx, field, true, isSuper);
    }

    private MemberDefinition getAccessMember(Environment env, Context ctx,
                                             MemberDefinition field,
                                             boolean isUpdate,
                                             boolean isSuper) {

        // The 'isSuper' argument is really only meaningful when the
        // target member is a method, in which case an 'invokespecial'
        // is needed.  For fields, 'getfield' and 'putfield' instructions
        // are generated in either case, and 'isSuper' currently plays
        // no essential role.  Nonetheless, we maintain the distinction
        // consistently for the time being.

        boolean isStatic = field.isStatic();
        boolean isMethod = field.isMethod();

        // Find pre-existing access method.
        // In the case of a field access method, we only look for the getter.
        // A getter is always created whenever a setter is.
        // QUERY: Why doesn't the 'MemberDefinition' object for the field
        // itself just have fields for its getter and setter?
        MemberDefinition af;
        for (af = getFirstMember(); af != null; af = af.getNextMember()) {
            if (af.getAccessMethodTarget() == field) {
                if (isMethod && af.isSuperAccessMethod() == isSuper) {
                    break;
                }
                // Distinguish the getter and the setter by the number of
                // arguments.
                int nargs = af.getType().getArgumentTypes().length;
                // This was (nargs == (isStatic ? 0 : 1) + (isUpdate ? 1 : 0))
                // in order to find a setter as well as a getter.  This caused
                // allocation of multiple getters.
                if (nargs == (isStatic ? 0 : 1)) {
                    break;
                }
            }
        }

        if (af != null) {
            if (!isUpdate) {
                return af;
            } else {
                MemberDefinition uf = af.getAccessUpdateMember();
                if (uf != null) {
                    return uf;
                }
            }
        } else if (isUpdate) {
            // must find or create the getter before creating the setter
            af = getAccessMember(env, ctx, field, false, isSuper);
        }

        // If we arrive here, we are creating a new access member.

        Identifier anm;
        Type dummyType = null;

        if (field.isConstructor()) {
            // For a constructor, we use the same name as for all
            // constructors ("<init>"), but add a distinguishing
            // argument of an otherwise unused "dummy" type.
            anm = idInit;
            // Get the dummy class, creating it if necessary.
            SourceClass outerMostClass = (SourceClass)getTopClass();
            dummyType = outerMostClass.dummyArgumentType;
            if (dummyType == null) {
                // Create dummy class.
                IdentifierToken sup =
                    new IdentifierToken(0, idJavaLangObject);
                IdentifierToken interfaces[] = {};
                IdentifierToken t = new IdentifierToken(0, idNull);
                int mod = M_ANONYMOUS | M_STATIC | M_SYNTHETIC;
                // If an interface has a public inner class, the dummy class for
                // the constructor must always be accessible. Fix for 4221648.
                if (outerMostClass.isInterface()) {
                    mod |= M_PUBLIC;
                }
                ClassDefinition dummyClass =
                    toplevelEnv.makeClassDefinition(toplevelEnv,
                                                    0, t, null, mod,
                                                    sup, interfaces,
                                                    outerMostClass);
                // Check the class.
                // It is likely that a full check is not really necessary,
                // but it is essential that the class be marked as parsed.
                dummyClass.getClassDeclaration().setDefinition(dummyClass, CS_PARSED);
                Expression argsX[] = {};
                Type argTypesX[] = {};
                try {
                    ClassDefinition supcls =
                        toplevelEnv.getClassDefinition(idJavaLangObject);
                    dummyClass.checkLocalClass(toplevelEnv, null,
                                               new Vset(), supcls, argsX, argTypesX);
                } catch (ClassNotFound ee) {};
                // Get class type.
                dummyType = dummyClass.getType();
                outerMostClass.dummyArgumentType = dummyType;
            }
        } else {
            // Otherwise, we use the name "access$N", for the
            // smallest value of N >= 0 yielding an unused name.
            for (int i = 0; ; i++) {
                anm = Identifier.lookup(prefixAccess + i);
                if (getFirstMatch(anm) == null) {
                    break;
                }
            }
        }

        Type argTypes[];
        Type t = field.getType();

        if (isStatic) {
            if (!isMethod) {
                if (!isUpdate) {
                    Type at[] = { };
                    argTypes = at;
                    t = Type.tMethod(t); // nullary getter
                } else {
                    Type at[] = { t };
                    argTypes = at;
                    t = Type.tMethod(Type.tVoid, argTypes); // unary setter
                }
            } else {
                // Since constructors are never static, we don't
                // have to worry about a dummy argument here.
                argTypes = t.getArgumentTypes();
            }
        } else {
            // All access methods for non-static members get an explicit
            // 'this' pointer as an extra argument, as the access methods
            // themselves must be static. EXCEPTION: Access methods for
            // constructors are non-static.
            Type classType = this.getType();
            if (!isMethod) {
                if (!isUpdate) {
                    Type at[] = { classType };
                    argTypes = at;
                    t = Type.tMethod(t, argTypes); // nullary getter
                } else {
                    Type at[] = { classType, t };
                    argTypes = at;
                    t = Type.tMethod(Type.tVoid, argTypes); // unary setter
                }
            } else {
                // Target is a method, possibly a constructor.
                Type at[] = t.getArgumentTypes();
                int nargs = at.length;
                if (field.isConstructor()) {
                    // Access method is a constructor.
                    // Requires a dummy argument.
                    MemberDefinition outerThisArg =
                        ((SourceMember)field).getOuterThisArg();
                    if (outerThisArg != null) {
                        // Outer instance link must be the first argument.
                        // The following is a sanity check that will catch
                        // most cases in which in this requirement is violated.
                        if (at[0] != outerThisArg.getType()) {
                            throw new CompilerError("misplaced outer this");
                        }
                        // Strip outer 'this' argument.
                        // It will be added back when the access method is checked.
                        argTypes = new Type[nargs];
                        argTypes[0] = dummyType;
                        for (int i = 1; i < nargs; i++) {
                            argTypes[i] = at[i];
                        }
                    } else {
                        // There is no outer instance.
                        argTypes = new Type[nargs+1];
                        argTypes[0] = dummyType;
                        for (int i = 0; i < nargs; i++) {
                            argTypes[i+1] = at[i];
                        }
                    }
                } else {
                    // Access method is static.
                    // Requires an explicit 'this' argument.
                    argTypes = new Type[nargs+1];
                    argTypes[0] = classType;
                    for (int i = 0; i < nargs; i++) {
                        argTypes[i+1] = at[i];
                    }
                }
                t = Type.tMethod(t.getReturnType(), argTypes);
            }
        }

        int nlen = argTypes.length;
        long where = field.getWhere();
        IdentifierToken names[] = new IdentifierToken[nlen];
        for (int i = 0; i < nlen; i++) {
            names[i] = new IdentifierToken(where, Identifier.lookup("$"+i));
        }

        Expression access = null;
        Expression thisArg = null;
        Expression args[] = null;

        if (isStatic) {
            args = new Expression[nlen];
            for (int i = 0 ; i < nlen ; i++) {
                args[i] = new IdentifierExpression(names[i]);
            }
        } else {
            if (field.isConstructor()) {
                // Constructor access method is non-static, so
                // 'this' works normally.
                thisArg = new ThisExpression(where);
                // Remove dummy argument, as it is not
                // passed to the target method.
                args = new Expression[nlen-1];
                for (int i = 1 ; i < nlen ; i++) {
                    args[i-1] = new IdentifierExpression(names[i]);
                }
            } else {
                // Non-constructor access method is static, so
                // we use the first argument as 'this'.
                thisArg = new IdentifierExpression(names[0]);
                // Remove first argument.
                args = new Expression[nlen-1];
                for (int i = 1 ; i < nlen ; i++) {
                    args[i-1] = new IdentifierExpression(names[i]);
                }
            }
            access = thisArg;
        }

        if (!isMethod) {
            access = new FieldExpression(where, access, field);
            if (isUpdate) {
                access = new AssignExpression(where, access, args[0]);
            }
        } else {
            // If true, 'isSuper' forces a non-virtual call.
            access = new MethodExpression(where, access, field, args, isSuper);
        }

        Statement code;
        if (t.getReturnType().isType(TC_VOID)) {
            code = new ExpressionStatement(where, access);
        } else {
            code = new ReturnStatement(where, access);
        }
        Statement body[] = { code };
        code = new CompoundStatement(where, body);

        // Access methods are now static (constructors excepted), and no longer final.
        // This change was mandated by the interaction of the access method
        // naming conventions and the restriction against overriding final
        // methods.
        int mod = M_SYNTHETIC;
        if (!field.isConstructor()) {
            mod |= M_STATIC;
        }

        // Create the synthetic method within the class in which the referenced
        // private member appears.  The 'env' argument to 'makeMemberDefinition'
        // is suspect because it represents the environment at the point at
        // which a reference takes place, while it should represent the
        // environment in which the definition of the synthetic method appears.
        // We get away with this because 'env' is used only to access globals
        // such as 'Environment.error', and also as an argument to
        // 'resolveTypeStructure', which immediately discards it using
        // 'setupEnv'. Apparently, the current definition of 'setupEnv'
        // represents a design change that has not been thoroughly propagated.
        // An access method is declared with same list of exceptions as its
        // target. As the exceptions are simply listed by name, the correctness
        // of this approach requires that the access method be checked
        // (name-resolved) in the same context as its target method  This
        // should always be the case.
        SourceMember newf = (SourceMember)
            env.makeMemberDefinition(env, where, this,
                                     null, mod, t, anm, names,
                                     field.getExceptionIds(), code);
        // Just to be safe, copy over the name-resolved exceptions from the
        // target so that the context in which the access method is checked
        // doesn't matter.
        newf.setExceptions(field.getExceptions(env));

        newf.setAccessMethodTarget(field);
        if (isUpdate) {
            af.setAccessUpdateMember(newf);
        }
        newf.setIsSuperAccessMethod(isSuper);

        // The call to 'check' is not needed, as the access method will be
        // checked by the containing class after it is added.  This is the
        // idiom followed in the implementation of class literals. (See
        // 'FieldExpression.java'.) In any case, the context is wrong in the
        // call below.  The access method must be checked in the context in
        // which it is declared, i.e., the class containing the referenced
        // private member, not the (inner) class in which the original member
        // reference occurs.
        //
        // try {
        //     newf.check(env, ctx, new Vset());
        // } catch (ClassNotFound ee) {
        //     env.error(where, "class.not.found", ee.name, this);
        // }

        // The comment above is inaccurate.  While it is often the case
        // that the containing class will check the access method, this is
        // by no means guaranteed.  In fact, an access method may be added
        // after the checking of its class is complete.  In this case, however,
        // the context in which the class was checked will have been saved in
        // the class definition object (by the fix for 4095716), allowing us
        // to check the field now, and in the correct context.
        // This fixes bug 4098093.

        Context checkContext = newf.getClassDefinition().getClassContext();
        if (checkContext != null) {
            //System.out.println("checking late addition: " + this);
            try {
                newf.check(env, checkContext, new Vset());
            } catch (ClassNotFound ee) {
                env.error(where, "class.not.found", ee.name, this);
            }
        }


        //System.out.println("[Access member '" +
        //                      newf + "' created for field '" +
        //                      field +"' in class '" + this + "']");

        return newf;
    }

    /**
     * Find an inner class of 'this', chosen arbitrarily.
     * Result is always an actual class, never an interface.
     * Returns null if none found.
     */
    SourceClass findLookupContext() {
        // Look for an immediate inner class.
        for (MemberDefinition f = getFirstMember();
             f != null;
             f = f.getNextMember()) {
            if (f.isInnerClass()) {
                SourceClass ic = (SourceClass)f.getInnerClass();
                if (!ic.isInterface()) {
                    return ic;
                }
            }
        }
        // Look for a class nested within an immediate inner interface.
        // At this point, we have given up on finding a minimally-nested
        // class (which would require a breadth-first traversal).  It doesn't
        // really matter which inner class we find.
        for (MemberDefinition f = getFirstMember();
             f != null;
             f = f.getNextMember()) {
            if (f.isInnerClass()) {
                SourceClass lc =
                    ((SourceClass)f.getInnerClass()).findLookupContext();
                if (lc != null) {
                    return lc;
                }
            }
        }
        // No inner classes.
        return null;
    }

    private MemberDefinition lookup = null;

    /**
     * Get helper method for class literal lookup.
     */
    public MemberDefinition getClassLiteralLookup(long fwhere) {

        // If we have already created a lookup method, reuse it.
        if (lookup != null) {
            return lookup;
        }

        // If the current class is a nested class, make sure we put the
        // lookup method in the outermost class.  Set 'lookup' for the
        // intervening inner classes so we won't have to do the search
        // again.
        if (outerClass != null) {
            lookup = outerClass.getClassLiteralLookup(fwhere);
            return lookup;
        }

        // If we arrive here, there was no existing 'class$' method.

        ClassDefinition c = this;
        boolean needNewClass = false;

        if (isInterface()) {
            // The top-level type is an interface.  Try to find an existing
            // inner class in which to create the helper method.  Any will do.
            c = findLookupContext();
            if (c == null) {
                // The interface has no inner classes.  Create an anonymous
                // inner class to hold the helper method, as an interface must
                // not have any methods.  The tests above for prior creation
                // of a 'class$' method assure that only one such class is
                // allocated for each outermost class containing a class
                // literal embedded somewhere within.  Part of fix for 4055017.
                needNewClass = true;
                IdentifierToken sup =
                    new IdentifierToken(fwhere, idJavaLangObject);
                IdentifierToken interfaces[] = {};
                IdentifierToken t = new IdentifierToken(fwhere, idNull);
                int mod = M_PUBLIC | M_ANONYMOUS | M_STATIC | M_SYNTHETIC;
                c = (SourceClass)
                    toplevelEnv.makeClassDefinition(toplevelEnv,
                                                    fwhere, t, null, mod,
                                                    sup, interfaces, this);
            }
        }


        // The name of the class-getter stub is "class$"
        Identifier idDClass = Identifier.lookup(prefixClass);
        Type strarg[] = { Type.tString };

        // Some sanity checks of questionable value.
        //
        // This check became useless after matchMethod() was modified
        // to not return synthetic methods.
        //
        //try {
        //    lookup = c.matchMethod(toplevelEnv, c, idDClass, strarg);
        //} catch (ClassNotFound ee) {
        //    throw new CompilerError("unexpected missing class");
        //} catch (AmbiguousMember ee) {
        //    throw new CompilerError("synthetic name clash");
        //}
        //if (lookup != null && lookup.getClassDefinition() == c) {
        //    // Error if method found was not inherited.
        //    throw new CompilerError("unexpected duplicate");
        //}
        // Some sanity checks of questionable value.

        /*  // The helper function looks like this.
         *  // It simply maps a checked exception to an unchecked one.
         *  static Class class$(String class$) {
         *    try { return Class.forName(class$); }
         *    catch (ClassNotFoundException forName) {
         *      throw new NoClassDefFoundError(forName.getMessage());
         *    }
         *  }
         */
        long w = c.getWhere();
        IdentifierToken arg = new IdentifierToken(w, idDClass);
        Expression e = new IdentifierExpression(arg);
        Expression a1[] = { e };
        Identifier idForName = Identifier.lookup("forName");
        e = new MethodExpression(w, new TypeExpression(w, Type.tClassDesc),
                                 idForName, a1);
        Statement body = new ReturnStatement(w, e);
        // map the exceptions
        Identifier idClassNotFound =
            Identifier.lookup("java.lang.ClassNotFoundException");
        Identifier idNoClassDefFound =
            Identifier.lookup("java.lang.NoClassDefFoundError");
        Type ctyp = Type.tClass(idClassNotFound);
        Type exptyp = Type.tClass(idNoClassDefFound);
        Identifier idGetMessage = Identifier.lookup("getMessage");
        e = new IdentifierExpression(w, idForName);
        e = new MethodExpression(w, e, idGetMessage, new Expression[0]);
        Expression a2[] = { e };
        e = new NewInstanceExpression(w, new TypeExpression(w, exptyp), a2);
        Statement handler = new CatchStatement(w, new TypeExpression(w, ctyp),
                                               new IdentifierToken(idForName),
                                               new ThrowStatement(w, e));
        Statement handlers[] = { handler };
        body = new TryStatement(w, body, handlers);

        Type mtype = Type.tMethod(Type.tClassDesc, strarg);
        IdentifierToken args[] = { arg };

        // Use default (package) access.  If private, an access method would
        // be needed in the event that the class literal belonged to an interface.
        // Also, making it private tickles bug 4098316.
        lookup = toplevelEnv.makeMemberDefinition(toplevelEnv, w,
                                                  c, null,
                                                  M_STATIC | M_SYNTHETIC,
                                                  mtype, idDClass,
                                                  args, null, body);

        // If a new class was created to contain the helper method,
        // check it now.
        if (needNewClass) {
            if (c.getClassDeclaration().getStatus() == CS_CHECKED) {
                throw new CompilerError("duplicate check");
            }
            c.getClassDeclaration().setDefinition(c, CS_PARSED);
            Expression argsX[] = {};
            Type argTypesX[] = {};
            try {
                ClassDefinition sup =
                    toplevelEnv.getClassDefinition(idJavaLangObject);
                c.checkLocalClass(toplevelEnv, null,
                                  new Vset(), sup, argsX, argTypesX);
            } catch (ClassNotFound ee) {};
        }

        return lookup;
    }


    /**
     * A list of active ongoing compilations. This list
     * is used to stop two compilations from saving the
     * same class.
     */
    private static Vector active = new Vector();

    /**
     * Compile this class
     */
    public void compile(OutputStream out)
                throws InterruptedException, IOException {
        Environment env = toplevelEnv;
        synchronized (active) {
            while (active.contains(getName())) {
                active.wait();
            }
            active.addElement(getName());
        }

        try {
            compileClass(env, out);
        } catch (ClassNotFound e) {
            throw new CompilerError(e);
        } finally {
            synchronized (active) {
                active.removeElement(getName());
                active.notifyAll();
            }
        }
    }

    /**
     * Verify that the modifier bits included in 'required' are
     * all present in 'mods', otherwise signal an internal error.
     * Note that errors in the source program may corrupt the modifiers,
     * thus we rely on the fact that 'CompilerError' exceptions are
     * silently ignored after an error message has been issued.
     */
    private static void assertModifiers(int mods, int required) {
        if ((mods & required) != required) {
            throw new CompilerError("illegal class modifiers");
        }
    }

    protected void compileClass(Environment env, OutputStream out)
                throws IOException, ClassNotFound {
        Vector variables = new Vector();
        Vector methods = new Vector();
        Vector innerClasses = new Vector();
        CompilerMember init = new CompilerMember(new MemberDefinition(getWhere(), this, M_STATIC, Type.tMethod(Type.tVoid), idClassInit, null, null), new Assembler());
        Context ctx = new Context((Context)null, init.field);

        for (ClassDefinition def = this; def.isInnerClass(); def = def.getOuterClass()) {
            innerClasses.addElement(def);
        }
        // Reverse the order, so that outer levels come first:
        int ncsize = innerClasses.size();
        for (int i = ncsize; --i >= 0; )
            innerClasses.addElement(innerClasses.elementAt(i));
        for (int i = ncsize; --i >= 0; )
            innerClasses.removeElementAt(i);

        // System.out.println("compile class " + getName());

        boolean haveDeprecated = this.isDeprecated();
        boolean haveSynthetic = this.isSynthetic();
        boolean haveConstantValue = false;
        boolean haveExceptions = false;

        // Generate code for all fields
        for (SourceMember field = (SourceMember)getFirstMember();
             field != null;
             field = (SourceMember)field.getNextMember()) {

            //System.out.println("compile field " + field.getName());

            haveDeprecated |= field.isDeprecated();
            haveSynthetic |= field.isSynthetic();

            try {
                if (field.isMethod()) {
                    haveExceptions |=
                        (field.getExceptions(env).length > 0);

                    if (field.isInitializer()) {
                        if (field.isStatic()) {
                            field.code(env, init.asm);
                        }
                    } else {
                        CompilerMember f =
                            new CompilerMember(field, new Assembler());
                        field.code(env, f.asm);
                        methods.addElement(f);
                    }
                } else if (field.isInnerClass()) {
                    innerClasses.addElement(field.getInnerClass());
                } else if (field.isVariable()) {
                    field.inline(env);
                    CompilerMember f = new CompilerMember(field, null);
                    variables.addElement(f);
                    if (field.isStatic()) {
                        field.codeInit(env, ctx, init.asm);

                    }
                    haveConstantValue |=
                        (field.getInitialValue() != null);
                }
            } catch (CompilerError ee) {
                ee.printStackTrace();
                env.error(field, 0, "generic",
                          field.getClassDeclaration() + ":" + field +
                          "@" + ee.toString(), null, null);
            }
        }
        if (!init.asm.empty()) {
           init.asm.add(getWhere(), opc_return, true);
            methods.addElement(init);
        }

        // bail out if there were any errors
        if (getNestError()) {
            return;
        }

        int nClassAttrs = 0;

        // Insert constants
        if (methods.size() > 0) {
            tab.put("Code");
        }
        if (haveConstantValue) {
            tab.put("ConstantValue");
        }

        String sourceFile = null;
        if (env.debug_source()) {
            sourceFile = ((ClassFile)getSource()).getName();
            tab.put("SourceFile");
            tab.put(sourceFile);
            nClassAttrs += 1;
        }

        if (haveExceptions) {
            tab.put("Exceptions");
        }

        if (env.debug_lines()) {
            tab.put("LineNumberTable");
        }
        if (haveDeprecated) {
            tab.put("Deprecated");
            if (this.isDeprecated()) {
                nClassAttrs += 1;
            }
        }
        if (haveSynthetic) {
            tab.put("Synthetic");
            if (this.isSynthetic()) {
                nClassAttrs += 1;
            }
        }
// JCOV
        if (env.coverage()) {
            nClassAttrs += 2;           // AbsoluteSourcePath, TimeStamp
            tab.put("AbsoluteSourcePath");
            tab.put("TimeStamp");
            tab.put("CoverageTable");
        }
// end JCOV
        if (env.debug_vars()) {
            tab.put("LocalVariableTable");
        }
        if (innerClasses.size() > 0) {
            tab.put("InnerClasses");
            nClassAttrs += 1;           // InnerClasses
        }

// JCOV
        String absoluteSourcePath = "";
        long timeStamp = 0;

        if (env.coverage()) {
                absoluteSourcePath = getAbsoluteName();
                timeStamp = System.currentTimeMillis();
                tab.put(absoluteSourcePath);
        }
// end JCOV
        tab.put(getClassDeclaration());
        if (getSuperClass() != null) {
            tab.put(getSuperClass());
        }
        for (int i = 0 ; i < interfaces.length ; i++) {
            tab.put(interfaces[i]);
        }

        // Sort the methods in order to make sure both constant pool
        // entries and methods are in a deterministic order from run
        // to run (this allows comparing class files for a fixed point
        // to validate the compiler)
        CompilerMember[] ordered_methods =
            new CompilerMember[methods.size()];
        methods.copyInto(ordered_methods);
        java.util.Arrays.sort(ordered_methods);
        for (int i=0; i<methods.size(); i++)
            methods.setElementAt(ordered_methods[i], i);

        // Optimize Code and Collect method constants
        for (Enumeration e = methods.elements() ; e.hasMoreElements() ; ) {
            CompilerMember f = (CompilerMember)e.nextElement();
            try {
                f.asm.optimize(env);
                f.asm.collect(env, f.field, tab);
                tab.put(f.name);
                tab.put(f.sig);
                ClassDeclaration exp[] = f.field.getExceptions(env);
                for (int i = 0 ; i < exp.length ; i++) {
                    tab.put(exp[i]);
                }
            } catch (Exception ee) {
                ee.printStackTrace();
                env.error(f.field, -1, "generic", f.field.getName() + "@" + ee.toString(), null, null);
                f.asm.listing(System.out);
            }
        }

        // Collect field constants
        for (Enumeration e = variables.elements() ; e.hasMoreElements() ; ) {
            CompilerMember f = (CompilerMember)e.nextElement();
            tab.put(f.name);
            tab.put(f.sig);

            Object val = f.field.getInitialValue();
            if (val != null) {
                tab.put((val instanceof String) ? new StringExpression(f.field.getWhere(), (String)val) : val);
            }
        }

        // Collect inner class constants
        for (Enumeration e = innerClasses.elements();
             e.hasMoreElements() ; ) {
            ClassDefinition inner = (ClassDefinition)e.nextElement();
            tab.put(inner.getClassDeclaration());

            // If the inner class is local, we do not need to add its
            // outer class here -- the outer_class_info_index is zero.
            if (!inner.isLocal()) {
                ClassDefinition outer = inner.getOuterClass();
                tab.put(outer.getClassDeclaration());
            }

            // If the local name of the class is idNull, don't bother to
            // add it to the constant pool.  We won't need it.
            Identifier inner_local_name = inner.getLocalName();
            if (inner_local_name != idNull) {
                tab.put(inner_local_name.toString());
            }
        }

        // Write header
        DataOutputStream data = new DataOutputStream(out);
        data.writeInt(JAVA_MAGIC);
        data.writeShort(toplevelEnv.getMinorVersion());
        data.writeShort(toplevelEnv.getMajorVersion());
        tab.write(env, data);

        // Write class information
        int cmods = getModifiers() & MM_CLASS;

        // Certain modifiers are implied:
        // 1.  Any interface (nested or not) is implicitly deemed to be abstract,
        //     whether it is explicitly marked so or not.  (Java 1.0.)
        // 2.  A interface which is a member of a type is implicitly deemed to
        //     be static, whether it is explicitly marked so or not.
        // 3a. A type which is a member of an interface is implicitly deemed
        //     to be public, whether it is explicitly marked so or not.
        // 3b. A type which is a member of an interface is implicitly deemed
        //     to be static, whether it is explicitly marked so or not.
        // All of these rules are implemented in 'BatchParser.beginClass',
        // but the results are verified here.

        if (isInterface()) {
            // Rule 1.
            // The VM spec states that ACC_ABSTRACT must be set when
            // ACC_INTERFACE is; this was not done by javac prior to 1.2,
            // and the runtime compensates by setting it.  Making sure
            // it is set here will allow the runtime hack to eventually
            // be removed. Rule 2 doesn't apply to transformed modifiers.
            assertModifiers(cmods, ACC_ABSTRACT);
        } else {
            // Contrary to the JVM spec, we only set ACC_SUPER for classes,
            // not interfaces.  This is a workaround for a bug in IE3.0,
            // which refuses interfaces with ACC_SUPER on.
            cmods |= ACC_SUPER;
        }

        // If this is a nested class, transform access modifiers.
        if (outerClass != null) {
            // If private, transform to default (package) access.
            // If protected, transform to public.
            // M_PRIVATE and M_PROTECTED are already masked off by MM_CLASS above.
            // cmods &= ~(M_PRIVATE | M_PROTECTED);
            if (isProtected()) cmods |= M_PUBLIC;
            // Rule 3a.  Note that Rule 3b doesn't apply to transformed modifiers.
            if (outerClass.isInterface()) {
                assertModifiers(cmods, M_PUBLIC);
            }
        }

        data.writeShort(cmods);

        if (env.dumpModifiers()) {
            Identifier cn = getName();
            Identifier nm =
                Identifier.lookup(cn.getQualifier(), cn.getFlatName());
            System.out.println();
            System.out.println("CLASSFILE  " + nm);
            System.out.println("---" + classModifierString(cmods));
        }

        data.writeShort(tab.index(getClassDeclaration()));
        data.writeShort((getSuperClass() != null) ? tab.index(getSuperClass()) : 0);
        data.writeShort(interfaces.length);
        for (int i = 0 ; i < interfaces.length ; i++) {
            data.writeShort(tab.index(interfaces[i]));
        }

        // write variables
        ByteArrayOutputStream buf = new ByteArrayOutputStream(256);
        ByteArrayOutputStream attbuf = new ByteArrayOutputStream(256);
        DataOutputStream databuf = new DataOutputStream(buf);

        data.writeShort(variables.size());
        for (Enumeration e = variables.elements() ; e.hasMoreElements() ; ) {
            CompilerMember f = (CompilerMember)e.nextElement();
            Object val = f.field.getInitialValue();

            data.writeShort(f.field.getModifiers() & MM_FIELD);
            data.writeShort(tab.index(f.name));
            data.writeShort(tab.index(f.sig));

            int fieldAtts = (val != null ? 1 : 0);
            boolean dep = f.field.isDeprecated();
            boolean syn = f.field.isSynthetic();
            fieldAtts += (dep ? 1 : 0) + (syn ? 1 : 0);

            data.writeShort(fieldAtts);
            if (val != null) {
                data.writeShort(tab.index("ConstantValue"));
                data.writeInt(2);
                data.writeShort(tab.index((val instanceof String) ? new StringExpression(f.field.getWhere(), (String)val) : val));
            }
            if (dep) {
                data.writeShort(tab.index("Deprecated"));
                data.writeInt(0);
            }
            if (syn) {
                data.writeShort(tab.index("Synthetic"));
                data.writeInt(0);
            }
        }

        // write methods

        data.writeShort(methods.size());
        for (Enumeration e = methods.elements() ; e.hasMoreElements() ; ) {
            CompilerMember f = (CompilerMember)e.nextElement();

            int xmods = f.field.getModifiers() & MM_METHOD;
            // Transform floating point modifiers.  M_STRICTFP
            // of member + status of enclosing class turn into
            // ACC_STRICT bit.
            if (((xmods & M_STRICTFP)!=0) || ((cmods & M_STRICTFP)!=0)) {
                xmods |= ACC_STRICT;
            } else {
                // Use the default
                if (env.strictdefault()) {
                    xmods |= ACC_STRICT;
                }
            }
            data.writeShort(xmods);

            data.writeShort(tab.index(f.name));
            data.writeShort(tab.index(f.sig));
            ClassDeclaration exp[] = f.field.getExceptions(env);
            int methodAtts = ((exp.length > 0) ? 1 : 0);
            boolean dep = f.field.isDeprecated();
            boolean syn = f.field.isSynthetic();
            methodAtts += (dep ? 1 : 0) + (syn ? 1 : 0);

            if (!f.asm.empty()) {
                data.writeShort(methodAtts+1);
                f.asm.write(env, databuf, f.field, tab);
                int natts = 0;
                if (env.debug_lines()) {
                    natts++;
                }
// JCOV
                if (env.coverage()) {
                    natts++;
                }
// end JCOV
                if (env.debug_vars()) {
                    natts++;
                }
                databuf.writeShort(natts);

                if (env.debug_lines()) {
                    f.asm.writeLineNumberTable(env, new DataOutputStream(attbuf), tab);
                    databuf.writeShort(tab.index("LineNumberTable"));
                    databuf.writeInt(attbuf.size());
                    attbuf.writeTo(buf);
                    attbuf.reset();
                }

//JCOV
                if (env.coverage()) {
                    f.asm.writeCoverageTable(env, (ClassDefinition)this, new DataOutputStream(attbuf), tab, f.field.getWhere());
                    databuf.writeShort(tab.index("CoverageTable"));
                    databuf.writeInt(attbuf.size());
                    attbuf.writeTo(buf);
                    attbuf.reset();
                }
// end JCOV
                if (env.debug_vars()) {
                    f.asm.writeLocalVariableTable(env, f.field, new DataOutputStream(attbuf), tab);
                    databuf.writeShort(tab.index("LocalVariableTable"));
                    databuf.writeInt(attbuf.size());
                    attbuf.writeTo(buf);
                    attbuf.reset();
                }

                data.writeShort(tab.index("Code"));
                data.writeInt(buf.size());
                buf.writeTo(data);
                buf.reset();
            } else {
//JCOV
                if ((env.coverage()) && ((f.field.getModifiers() & M_NATIVE) > 0))
                    f.asm.addNativeToJcovTab(env, (ClassDefinition)this);
// end JCOV
                data.writeShort(methodAtts);
            }

            if (exp.length > 0) {
                data.writeShort(tab.index("Exceptions"));
                data.writeInt(2 + exp.length * 2);
                data.writeShort(exp.length);
                for (int i = 0 ; i < exp.length ; i++) {
                    data.writeShort(tab.index(exp[i]));
                }
            }
            if (dep) {
                data.writeShort(tab.index("Deprecated"));
                data.writeInt(0);
            }
            if (syn) {
                data.writeShort(tab.index("Synthetic"));
                data.writeInt(0);
            }
        }

        // class attributes
        data.writeShort(nClassAttrs);

        if (env.debug_source()) {
            data.writeShort(tab.index("SourceFile"));
            data.writeInt(2);
            data.writeShort(tab.index(sourceFile));
        }

        if (this.isDeprecated()) {
            data.writeShort(tab.index("Deprecated"));
            data.writeInt(0);
        }
        if (this.isSynthetic()) {
            data.writeShort(tab.index("Synthetic"));
            data.writeInt(0);
        }

// JCOV
        if (env.coverage()) {
            data.writeShort(tab.index("AbsoluteSourcePath"));
            data.writeInt(2);
            data.writeShort(tab.index(absoluteSourcePath));
            data.writeShort(tab.index("TimeStamp"));
            data.writeInt(8);
            data.writeLong(timeStamp);
        }
// end JCOV

        if (innerClasses.size() > 0) {
            data.writeShort(tab.index("InnerClasses"));
            data.writeInt(2 + 2*4*innerClasses.size());
            data.writeShort(innerClasses.size());
            for (Enumeration e = innerClasses.elements() ;
                 e.hasMoreElements() ; ) {
                // For each inner class name transformation, we have a record
                // with the following fields:
                //
                //    u2 inner_class_info_index;   // CONSTANT_Class_info index
                //    u2 outer_class_info_index;   // CONSTANT_Class_info index
                //    u2 inner_name_index;         // CONSTANT_Utf8_info index
                //    u2 inner_class_access_flags; // access_flags bitmask
                //
                // The spec states that outer_class_info_index is 0 iff
                // the inner class is not a member of its enclosing class (i.e.
                // it is a local or anonymous class).  The spec also states
                // that if a class is anonymous then inner_name_index should
                // be 0.
                //
                // See also the initInnerClasses() method in BinaryClass.java.

                // Generate inner_class_info_index.
                ClassDefinition inner = (ClassDefinition)e.nextElement();
                data.writeShort(tab.index(inner.getClassDeclaration()));

                // Generate outer_class_info_index.
                //
                // Checking isLocal() should probably be enough here,
                // but the check for isAnonymous is added for good
                // measure.
                if (inner.isLocal() || inner.isAnonymous()) {
                    data.writeShort(0);
                } else {
                    // Query: what about if inner.isInsideLocal()?
                    // For now we continue to generate a nonzero
                    // outer_class_info_index.
                    ClassDefinition outer = inner.getOuterClass();
                    data.writeShort(tab.index(outer.getClassDeclaration()));
                }

                // Generate inner_name_index.
                Identifier inner_name = inner.getLocalName();
                if (inner_name == idNull) {
                    if (!inner.isAnonymous()) {
                        throw new CompilerError("compileClass(), anonymous");
                    }
                    data.writeShort(0);
                } else {
                    data.writeShort(tab.index(inner_name.toString()));
                }

                // Generate inner_class_access_flags.
                int imods = inner.getInnerClassMember().getModifiers()
                            & ACCM_INNERCLASS;

                // Certain modifiers are implied for nested types.
                // See rules 1, 2, 3a, and 3b enumerated above.
                // All of these rules are implemented in 'BatchParser.beginClass',
                // but are verified here.

                if (inner.isInterface()) {
                    // Rules 1 and 2.
                    assertModifiers(imods, M_ABSTRACT | M_STATIC);
                }
                if (inner.getOuterClass().isInterface()) {
                    // Rules 3a and 3b.
                    imods &= ~(M_PRIVATE | M_PROTECTED); // error recovery
                    assertModifiers(imods, M_PUBLIC | M_STATIC);
                }

                data.writeShort(imods);

                if (env.dumpModifiers()) {
                    Identifier fn = inner.getInnerClassMember().getName();
                    Identifier nm =
                        Identifier.lookup(fn.getQualifier(), fn.getFlatName());
                    System.out.println("INNERCLASS " + nm);
                    System.out.println("---" + classModifierString(imods));
                }

            }
        }

        // Cleanup
        data.flush();
        tab = null;

// JCOV
        // generate coverage data
        if (env.covdata()) {
            Assembler CovAsm = new Assembler();
            CovAsm.GenVecJCov(env, (ClassDefinition)this, timeStamp);
        }
// end JCOV
    }

    /**
     * Print out the dependencies for this class (-xdepend) option
     */

    public void printClassDependencies(Environment env) {

        // Only do this if the -xdepend flag is on
        if ( toplevelEnv.print_dependencies() ) {

            // Name of java source file this class was in (full path)
            //    e.g. /home/ohair/Test.java
            String src = ((ClassFile)getSource()).getAbsoluteName();

            // Class name, fully qualified
            //   e.g. "java.lang.Object" or "FooBar" or "sun.tools.javac.Main"
            // Inner class names must be mangled, as ordinary '.' qualification
            // is used internally where the spec requires '$' separators.
            //   String className = getName().toString();
            String className = Type.mangleInnerType(getName()).toString();

            // Line number where class starts in the src file
            long startLine = getWhere() >> WHEREOFFSETBITS;

            // Line number where class ends in the src file (not used yet)
            long endLine = getEndPosition() >> WHEREOFFSETBITS;

            // First line looks like:
            //    CLASS:src,startLine,endLine,className
            System.out.println( "CLASS:"
                    + src               + ","
                    + startLine         + ","
                    + endLine   + ","
                    + className);

            // For each class this class is dependent on:
            //    CLDEP:className1,className2
            //  where className1 is the name of the class we are in, and
            //        classname2 is the name of the class className1
            //          is dependent on.
            for(Enumeration e = deps.elements();  e.hasMoreElements(); ) {
                ClassDeclaration data = (ClassDeclaration) e.nextElement();
                // Mangle name of class dependend on.
                String depName =
                    Type.mangleInnerType(data.getName()).toString();
                env.output("CLDEP:" + className + "," + depName);
            }
        }
    }
}
