attr.java

来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,568 行 · 第 1/5 页

JAVA
1,568
字号
        }        // Attribute finalizer        if (tree.finalizer != null) attribStat(tree.finalizer, env);        result = null;    }    public void visitConditional(JCConditional tree) {        attribExpr(tree.cond, env, syms.booleanType);        attribExpr(tree.truepart, env);        attribExpr(tree.falsepart, env);        result = check(tree,                       capture(condType(tree.pos(), tree.cond.type,                                        tree.truepart.type, tree.falsepart.type)),                       VAL, pkind, pt);    }    //where        /** Compute the type of a conditional expression, after         *  checking that it exists. See Spec 15.25.         *         *  @param pos      The source position to be used for         *                  error diagnostics.         *  @param condtype The type of the expression's condition.         *  @param thentype The type of the expression's then-part.         *  @param elsetype The type of the expression's else-part.         */        private Type condType(DiagnosticPosition pos,                              Type condtype,                              Type thentype,                              Type elsetype) {            Type ctype = condType1(pos, condtype, thentype, elsetype);            // If condition and both arms are numeric constants,            // evaluate at compile-time.            return ((condtype.constValue() != null) &&                    (thentype.constValue() != null) &&                    (elsetype.constValue() != null))                ? cfolder.coerce(condtype.isTrue()?thentype:elsetype, ctype)                : ctype;        }        /** Compute the type of a conditional expression, after         *  checking that it exists.  Does not take into         *  account the special case where condition and both arms         *  are constants.         *         *  @param pos      The source position to be used for error         *                  diagnostics.         *  @param condtype The type of the expression's condition.         *  @param thentype The type of the expression's then-part.         *  @param elsetype The type of the expression's else-part.         */        private Type condType1(DiagnosticPosition pos, Type condtype,                               Type thentype, Type elsetype) {            // If same type, that is the result            if (types.isSameType(thentype, elsetype))                return thentype.baseType();            Type thenUnboxed = (!allowBoxing || thentype.isPrimitive())                ? thentype : types.unboxedType(thentype);            Type elseUnboxed = (!allowBoxing || elsetype.isPrimitive())                ? elsetype : types.unboxedType(elsetype);            // Otherwise, if both arms can be converted to a numeric            // type, return the least numeric type that fits both arms            // (i.e. return larger of the two, or return int if one            // arm is short, the other is char).            if (thenUnboxed.isPrimitive() && elseUnboxed.isPrimitive()) {                // If one arm has an integer subrange type (i.e., byte,                // short, or char), and the other is an integer constant                // that fits into the subrange, return the subrange type.                if (thenUnboxed.tag < INT && elseUnboxed.tag == INT &&                    types.isAssignable(elseUnboxed, thenUnboxed))                    return thenUnboxed.baseType();                if (elseUnboxed.tag < INT && thenUnboxed.tag == INT &&                    types.isAssignable(thenUnboxed, elseUnboxed))                    return elseUnboxed.baseType();                for (int i = BYTE; i < VOID; i++) {                    Type candidate = syms.typeOfTag[i];                    if (types.isSubtype(thenUnboxed, candidate) &&                        types.isSubtype(elseUnboxed, candidate))                        return candidate;                }            }            // Those were all the cases that could result in a primitive            if (allowBoxing) {                if (thentype.isPrimitive())                    thentype = types.boxedClass(thentype).type;                if (elsetype.isPrimitive())                    elsetype = types.boxedClass(elsetype).type;            }            if (types.isSubtype(thentype, elsetype))                return elsetype.baseType();            if (types.isSubtype(elsetype, thentype))                return thentype.baseType();            if (!allowBoxing || thentype.tag == VOID || elsetype.tag == VOID) {                log.error(pos, "neither.conditional.subtype",                          thentype, elsetype);                return thentype.baseType();            }            // both are known to be reference types.  The result is            // lub(thentype,elsetype). This cannot fail, as it will            // always be possible to infer "Object" if nothing better.            return types.lub(thentype.baseType(), elsetype.baseType());        }    public void visitIf(JCIf tree) {        attribExpr(tree.cond, env, syms.booleanType);        attribStat(tree.thenpart, env);        if (tree.elsepart != null)            attribStat(tree.elsepart, env);        chk.checkEmptyIf(tree);        result = null;    }    public void visitExec(JCExpressionStatement tree) {        attribExpr(tree.expr, env);        result = null;    }    public void visitBreak(JCBreak tree) {        tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);        result = null;    }    public void visitContinue(JCContinue tree) {        tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);        result = null;    }    //where        /** Return the target of a break or continue statement, if it exists,         *  report an error if not.         *  Note: The target of a labelled break or continue is the         *  (non-labelled) statement tree referred to by the label,         *  not the tree representing the labelled statement itself.         *         *  @param pos     The position to be used for error diagnostics         *  @param tag     The tag of the jump statement. This is either         *                 Tree.BREAK or Tree.CONTINUE.         *  @param label   The label of the jump statement, or null if no         *                 label is given.         *  @param env     The environment current at the jump statement.         */        private JCTree findJumpTarget(DiagnosticPosition pos,                                    int tag,                                    Name label,                                    Env<AttrContext> env) {            // Search environments outwards from the point of jump.            Env<AttrContext> env1 = env;            LOOP:            while (env1 != null) {                switch (env1.tree.getTag()) {                case JCTree.LABELLED:                    JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;                    if (label == labelled.label) {                        // If jump is a continue, check that target is a loop.                        if (tag == JCTree.CONTINUE) {                            if (labelled.body.getTag() != JCTree.DOLOOP &&                                labelled.body.getTag() != JCTree.WHILELOOP &&                                labelled.body.getTag() != JCTree.FORLOOP &&                                labelled.body.getTag() != JCTree.FOREACHLOOP)                                log.error(pos, "not.loop.label", label);                            // Found labelled statement target, now go inwards                            // to next non-labelled tree.                            return TreeInfo.referencedStatement(labelled);                        } else {                            return labelled;                        }                    }                    break;                case JCTree.DOLOOP:                case JCTree.WHILELOOP:                case JCTree.FORLOOP:                case JCTree.FOREACHLOOP:                    if (label == null) return env1.tree;                    break;                case JCTree.SWITCH:                    if (label == null && tag == JCTree.BREAK) return env1.tree;                    break;                case JCTree.METHODDEF:                case JCTree.CLASSDEF:                    break LOOP;                default:                }                env1 = env1.next;            }            if (label != null)                log.error(pos, "undef.label", label);            else if (tag == JCTree.CONTINUE)                log.error(pos, "cont.outside.loop");            else                log.error(pos, "break.outside.switch.loop");            return null;        }    public void visitReturn(JCReturn tree) {        // Check that there is an enclosing method which is        // nested within than the enclosing class.        if (env.enclMethod == null ||            env.enclMethod.sym.owner != env.enclClass.sym) {            log.error(tree.pos(), "ret.outside.meth");        } else {            // Attribute return expression, if it exists, and check that            // it conforms to result type of enclosing method.            Symbol m = env.enclMethod.sym;            if (m.type.getReturnType().tag == VOID) {                if (tree.expr != null)                    log.error(tree.expr.pos(),                              "cant.ret.val.from.meth.decl.void");            } else if (tree.expr == null) {                log.error(tree.pos(), "missing.ret.val");            } else {                attribExpr(tree.expr, env, m.type.getReturnType());            }        }        result = null;    }    public void visitThrow(JCThrow tree) {        attribExpr(tree.expr, env, syms.throwableType);        result = null;    }    public void visitAssert(JCAssert tree) {        attribExpr(tree.cond, env, syms.booleanType);        if (tree.detail != null) {            chk.checkNonVoid(tree.detail.pos(), attribExpr(tree.detail, env));        }        result = null;    }     /** Visitor method for method invocations.     *  NOTE: The method part of an application will have in its type field     *        the return type of the method, not the method's type itself!     */    public void visitApply(JCMethodInvocation tree) {        // The local environment of a method application is        // a new environment nested in the current one.        Env<AttrContext> localEnv = env.dup(tree, env.info.dup());        // The types of the actual method arguments.        List<Type> argtypes;        // The types of the actual method type arguments.        List<Type> typeargtypes = null;        Name methName = TreeInfo.name(tree.meth);        boolean isConstructorCall =            methName == names._this || methName == names._super;        if (isConstructorCall) {            // We are seeing a ...this(...) or ...super(...) call.            // Check that this is the first statement in a constructor.            if (checkFirstConstructorStat(tree, env)) {                // Record the fact                // that this is a constructor call (using isSelfCall).                localEnv.info.isSelfCall = true;                // Attribute arguments, yielding list of argument types.                argtypes = attribArgs(tree.args, localEnv);                typeargtypes = attribTypes(tree.typeargs, localEnv);                // Variable `site' points to the class in which the called                // constructor is defined.                Type site = env.enclClass.sym.type;                if (methName == names._super) {                    if (site == syms.objectType) {                        log.error(tree.meth.pos(), "no.superclass", site);                        site = syms.errType;                    } else {                        site = types.supertype(site);                    }                }                if (site.tag == CLASS) {                    if (site.getEnclosingType().tag == CLASS) {                        // we are calling a nested class                        if (tree.meth.getTag() == JCTree.SELECT) {                            JCTree qualifier = ((JCFieldAccess) tree.meth).selected;                            // We are seeing a prefixed call, of the form                            //     <expr>.super(...).                            // Check that the prefix expression conforms                            // to the outer instance type of the class.                            chk.checkRefType(qualifier.pos(),                                             attribExpr(qualifier, localEnv,                                                        site.getEnclosingType()));                        } else if (methName == names._super) {                            // qualifier omitted; check for existence                            // of an appropriate implicit qualifier.                            rs.resolveImplicitThis(tree.meth.pos(),                                                   localEnv, site);                        }                    } else if (tree.meth.getTag() == JCTree.SELECT) {                        log.error(tree.meth.pos(), "illegal.qual.not.icls",                                  site.tsym);                    }                    // if we're calling a java.lang.Enum constructor,                    // prefix the implicit String and int parameters                    if (site.tsym == syms.enumSym && allowEnums)                        argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);                    // Resolve the called constructor under the assumption                    // that we are referring to a superclass instance of the                    // current instance (JLS ???).

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?