907 lines · 35.3 KB · Java
RawDownload
                int length = args.size();            outer_loop:                for (int i = 0; i < length; i++) {                    LocalMember lf = (LocalMember)(args.elementAt(i));                    Identifier name_i = lf.getName();                    for (int j = i + 1; j < length; j++) {                        LocalMember lf2 = (LocalMember)(args.elementAt(j));                        Identifier name_j = lf2.getName();                        if (name_i.equals(name_j)) {                            env.error(lf2.getWhere(), "duplicate.argument",                                      name_i);                            break outer_loop;                        }                    }                }            }             if (getValue() != null) {                ctx = new Context(ctx, this);                 if (isMethod()) {                    Statement s = (Statement)getValue();                    // initialize vset, indication that each of the arguments                    // to the function has a value                     for (Enumeration e = args.elements(); e.hasMoreElements();){                        LocalMember f = (LocalMember)e.nextElement();                        vset.addVar(ctx.declare(env, f));                    }                     if (isConstructor()) {                        // Undefine "this" in some constructors, until after                        // the super constructor has been called.                        vset.clearVar(ctx.getThisNumber());                         // If the first thing in the definition isn't a call                        // to either super() or this(), then insert one.                        Expression supCall = s.firstConstructor();                        if ((supCall == null)                            && (getClassDefinition().getSuperClass() != null)) {                            supCall = getDefaultSuperCall(env);                            Statement scs = new ExpressionStatement(where,                                                                    supCall);                            s = Statement.insertStatement(scs, s);                            setValue(s);                        }                    }                     //System.out.println("VSET = " + vset);                    ClassDeclaration exp[] = getExceptions(env);                    int htsize = (exp.length > 3) ? 17 : 7;                    Hashtable thrown = new Hashtable(htsize);                     vset = s.checkMethod(env, ctx, vset, thrown);                     ClassDeclaration ignore1 =                        env.getClassDeclaration(idJavaLangError);                    ClassDeclaration ignore2 =                        env.getClassDeclaration(idJavaLangRuntimeException);                     for (Enumeration e = thrown.keys(); e.hasMoreElements();) {                        ClassDeclaration c = (ClassDeclaration)e.nextElement();                        ClassDefinition def = c.getClassDefinition(env);                        if (def.subClassOf(env, ignore1)                                 || def.subClassOf(env, ignore2)) {                            continue;                        }                         boolean ok = false;                        if (!isInitializer()) {                            for (int i = 0 ; i < exp.length ; i++) {                                if (def.subClassOf(env, exp[i])) {                                    ok = true;                                }                            }                        }                        if (!ok) {                            Node n = (Node)thrown.get(c);                            long where = n.getWhere();                            String errorMsg;                             if (isConstructor()) {                                if (where ==                                    getClassDefinition().getWhere()) {                                     // If this message is being generated for                                    // a default constructor, we should give                                    // a different error message.  Currently                                    // we check for this by seeing if the                                    // constructor has the same "where" as                                    // its class.  This is a bit kludgy, but                                    // works. (bug id 4034836)                                    errorMsg = "def.constructor.exception";                                } else {                                    // Constructor with uncaught exception.                                    errorMsg = "constructor.exception";                                }                            } else if (isInitializer()) {                                // Initializer with uncaught exception.                                errorMsg = "initializer.exception";                            } else {                                // Method with uncaught exception.                                errorMsg = "uncaught.exception";                            }                            env.error(where, errorMsg, c.getName());                        }                    }                } else {                    Hashtable thrown = new Hashtable(3);  // small & throw-away                    Expression val = (Expression)getValue();                     vset = val.checkInitializer(env, ctx, vset,                                                getType(), thrown);                    setValue(val.convert(env, ctx, getType(), val));                     // Complain about static final members of inner classes that                    // do not have an initializer that is a constant expression.                    // In general, static members are not permitted for inner                    // classes, but an exception is made for named constants.                    // Other cases of static members, including non-final ones,                    // are handled in 'SourceClass'.  Part of fix for 4095568.                    if (isStatic() && isFinal() && !clazz.isTopLevel()) {                        if (!((Expression)getValue()).isConstant()) {                            env.error(where, "static.inner.field", getName(), this);                            setValue(null);                        }                    }                      // Both RuntimeExceptions and Errors should be                    // allowed in initializers.  Fix for bug 4102541.                    ClassDeclaration except =                         env.getClassDeclaration(idJavaLangThrowable);                    ClassDeclaration ignore1 =                        env.getClassDeclaration(idJavaLangError);                    ClassDeclaration ignore2 =                        env.getClassDeclaration(idJavaLangRuntimeException);                     for (Enumeration e = thrown.keys(); e.hasMoreElements(); ) {                        ClassDeclaration c = (ClassDeclaration)e.nextElement();                        ClassDefinition def = c.getClassDefinition(env);                         if (!def.subClassOf(env, ignore1)                            && !def.subClassOf(env, ignore2)                            && def.subClassOf(env, except)) {                            Node n = (Node)thrown.get(c);                            env.error(n.getWhere(),                                      "initializer.exception", c.getName());                        }                    }                }                if (env.dump()) {                    getValue().print(System.out);                    System.out.println();                }            }            status = getClassDefinition().getError() ? ERROR : CHECKED;        }          // Initializers (static and instance) must be able to complete normally.        if (isInitializer() && vset.isDeadEnd()) {            env.error(where, "init.no.normal.completion");            vset = vset.clearDeadEnd();        }         return vset;    }     // helper to check(): synthesize a missing super() call    private Expression getDefaultSuperCall(Environment env) {        Expression se = null;        ClassDefinition sclass = getClassDefinition().getSuperClass().getClassDefinition();        // does the superclass constructor require an enclosing instance?        ClassDefinition reqc = (sclass == null) ? null                             : sclass.isTopLevel() ? null                             : sclass.getOuterClass();        ClassDefinition thisc = getClassDefinition();        if (reqc != null && !Context.outerLinkExists(env, reqc, thisc)) {            se = new SuperExpression(where, new NullExpression(where));            env.error(where, "no.default.outer.arg", reqc, getClassDefinition());        }        if (se == null) {            se = new SuperExpression(where);        }        return new MethodExpression(where, se, idInit, new Expression[0]);    }     /**     * Inline the field     */    void inline(Environment env) throws ClassNotFound {        switch (status) {          case PARSED:            check(env);            inline(env);            break;           case CHECKED:            if (env.dump()) {                System.out.println("[inline field " + getClassDeclaration().getName() + "." + getName() + "]");            }            status = INLINING;            env = new Environment(env, this);             if (isMethod()) {                if ((!isNative()) && (!isAbstract())) {                    Statement s = (Statement)getValue();                    Context ctx = new Context((Context)null, this);                    for (Enumeration e = args.elements() ; e.hasMoreElements() ;) {                        LocalMember local = (LocalMember)e.nextElement();                        ctx.declare(env, local);                    }                    setValue(s.inline(env, ctx));                }            } else if (isInnerClass()) {                // some classes are checked and inlined separately                ClassDefinition nc = getInnerClass();                if (nc instanceof SourceClass && !nc.isLocal()                    && nc.isInsideLocal()) {                    status = INLINING;                    ((SourceClass)nc).inlineLocalClass(env);                }                status = INLINED;                break;            } else {                if (getValue() != null)  {                    Context ctx = new Context((Context)null, this);                    if (!isStatic()) {                        // Cf. "thisArg" in SourceClass.checkMembers().                        Context ctxInst = new Context(ctx, this);                        LocalMember thisArg =                                    ((SourceClass)clazz).getThisArgument();                        ctxInst.declare(env, thisArg);                        setValue(((Expression)getValue())                                    .inlineValue(env, ctxInst));                    } else {                        setValue(((Expression)getValue())                                    .inlineValue(env, ctx));                    }                }            }            if (env.dump()) {                System.out.println("[inlined field " + getClassDeclaration().getName() + "." + getName() + "]");                if (getValue() != null) {                    getValue().print(System.out);                    System.out.println();                } else {                    System.out.println("<empty>");                }            }            status = INLINED;            break;        }    }     /**     * Get the value of the field (or null if the value can't be determined)     */    public Node getValue(Environment env) throws ClassNotFound {        Node value = getValue();        if (value != null && status != INLINED) {            // be sure to get the imports right:            env = ((SourceClass)clazz).setupEnv(env);            inline(env);            value = (status == INLINED) ? getValue() : null;        }        return value;    }     public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound {        if (super.isInlineable(env, fromFinal)) {            getValue(env);            return (status == INLINED) && !getClassDefinition().getError();        }        return false;    }      /**     * Get the initial value of the field     */    public Object getInitialValue() {        if (isMethod() || (getValue() == null) || (!isFinal()) || (status != INLINED)) {            return null;        }        return ((Expression)getValue()).getValue();    }     /**     * Generate code     */    public void code(Environment env, Assembler asm) throws ClassNotFound {        switch (status) {          case PARSED:            check(env);            code(env, asm);            return;           case CHECKED:            inline(env);            code(env, asm);            return;           case INLINED:            // Actually generate code            if (env.dump()) {                System.out.println("[code field " + getClassDeclaration().getName() + "." + getName() + "]");            }            if (isMethod() && (!isNative()) && (!isAbstract())) {                env = new Environment(env, this);                Context ctx = new Context((Context)null, this);                Statement s = (Statement)getValue();                 for (Enumeration e = args.elements() ; e.hasMoreElements() ; ) {                    LocalMember f = (LocalMember)e.nextElement();                    ctx.declare(env, f);                    //ctx.declare(env, (LocalMember)e.nextElement());                }                 /*                if (isConstructor() && ((s == null) || (s.firstConstructor() == null))) {                    ClassDeclaration c = getClassDefinition().getSuperClass();                    if (c != null) {                        MemberDefinition field = c.getClassDefinition(env).matchMethod(env, getClassDefinition(), idInit);                        asm.add(getWhere(), opc_aload, new Integer(0));                        asm.add(getWhere(), opc_invokespecial, field);                        asm.add(getWhere(), opc_pop);                    }                     // Output initialization code                    for (MemberDefinition f = getClassDefinition().getFirstMember() ; f != null ; f = f.getNextMember()) {                        if (!f.isStatic()) {                            f.codeInit(env, ctx, asm);                        }                    }                }                */                if (s != null) {                    s.code(env, ctx, asm);                }                if (getType().getReturnType().isType(TC_VOID) && !isInitializer()) {                   asm.add(getWhere(), opc_return, true);                }            }            return;        }    }     public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound {        if (isMethod()) {            return;        }        switch (status) {          case PARSED:            check(env);            codeInit(env, ctx, asm);            return;           case CHECKED:            inline(env);            codeInit(env, ctx, asm);            return;           case INLINED:            // Actually generate code            if (env.dump()) {                System.out.println("[code initializer  " + getClassDeclaration().getName() + "." + getName() + "]");            }            if (getValue() != null) {                Expression e = (Expression)getValue();                // The JLS Section 8.5 specifies that static (non-final)                // initializers should be executed in textual order.  Eliding                // initializations to default values can interfere with this,                // so the tests for !e.equalsDefault() have been eliminated,                // below.                if (isStatic()) {                    if (getInitialValue() == null) {                        // removed: && !e.equalsDefault()) {                        e.codeValue(env, ctx, asm);                        asm.add(getWhere(), opc_putstatic, this);                    }                } else { // removed: if (!e.equalsDefault()) {                    // This code doesn't appear to be reached for                    // instance initializers.  Code for these is generated                    // in the makeVarInits() method of the class                    // MethodExpression.                    asm.add(getWhere(), opc_aload, new Integer(0));                    e.codeValue(env, ctx, asm);                    asm.add(getWhere(), opc_putfield, this);                }            }            return;        }    }     /**     * Print for debugging     */    public void print(PrintStream out) {        super.print(out);        if (getValue() != null) {            getValue().print(out);            out.println();        }    }}

Lines 501–907 of 907. Previous lines