2674 lines · 109.2 KB · Java
RawDownload
        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"};

Lines 1001–1500 of 2674. Previous lines