⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attr.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
                Type site = env.enclClass.sym.type;
                if (methName == names._super)
                    site = site.supertype();
                if (site.tag == CLASS) {
                    if (site.outer().tag == CLASS) {
                        if (tree.meth.tag == Tree.SELECT) {
                            Tree qualifier = ((Select) tree.meth).selected;
                            chk.checkRefType(qualifier.pos,
                                    attribExpr(qualifier, localEnv, site.outer()));
                        } else if (methName == names._super) {
                            rs.resolveImplicitThis(tree.meth.pos, localEnv, site);
                        }
                    } else if (tree.meth.tag == Tree.SELECT) {
                        log.error(tree.meth.pos, "illegal.qual.not.icls",
                                site.tsym.toJava());
                    }
                    boolean selectSuperPrev =
                            ((AttrContext) localEnv.info).selectSuper;
                    ((AttrContext) localEnv.info).selectSuper = true;
                    Symbol sym = rs.resolveConstructor(tree.meth.pos, localEnv, site,
                            argtypes);
                    ((AttrContext) localEnv.info).selectSuper = selectSuperPrev;
                    TreeInfo.setSymbol(tree.meth, sym);
                    List saved = methTemplateSupply.elems;
                    Type mpt = newMethTemplate(argtypes);
                    checkId(tree.meth, site, sym, env, MTH, mpt);
                    methTemplateSupply.elems = saved;
                }
            }
            result = syms.voidType;
        } else {
            argtypes = attribArgs(tree.args, localEnv);
            List saved = methTemplateSupply.elems;
            Type mpt = newMethTemplate(argtypes);
            Type mtype = attribExpr(tree.meth, localEnv, mpt);
            methTemplateSupply.elems = saved;
            result = check(tree, mtype.restype(), VAL, pkind, pt);
        }
    }

    /**
      * Check that given application node appears as first statement
      *  in a constructor call.
      *  @param tree   The application node
      *  @param env    The environment current at the application.
      */
    boolean checkFirstConstructorStat(Apply tree, Env env) {
        MethodDef enclMethod = env.enclMethod;
        if (enclMethod != null && enclMethod.name == names.init) {
            Block body = (Block) enclMethod.body;
            if (((Tree) body.stats.head).tag == Tree.EXEC &&
                    ((Exec) body.stats.head).expr == tree)
                return true;
        }
        log.error(tree.pos, "call.must.be.first.stmt.in.ctor",
                TreeInfo.name(tree.meth).toJava());
        return false;
    }

    /**
      * Optimization: To avoid allocating a new methodtype for every
      *  attribution of an Apply node, we use a reservoir.
      */
    ListBuffer methTemplateSupply = new ListBuffer();

    /**
     * Obtain an otherwise unused method type with given argument types.
     *  Take it from the reservoir if non-empty, or create a new one.
     */
    Type newMethTemplate(List argtypes) {
        if (methTemplateSupply.elems == methTemplateSupply.last)
            methTemplateSupply.append(
                    new MethodType(null, null, null, syms.methodClass));
        MethodType mt = (Type.MethodType) methTemplateSupply.elems.head;
        methTemplateSupply.elems = methTemplateSupply.elems.tail;
        mt.argtypes = argtypes;
        return mt;
    }

    public void visitNewClass(NewClass tree) {
        Type owntype = syms.errType;
        ClassDef cdef = tree.def;
        Tree clazz = tree.clazz;
        Tree clazzid = clazz;
        Tree clazzid1 = clazzid;
        if (tree.encl != null) {
            Type encltype =
                    chk.checkRefType(tree.encl.pos, attribExpr(tree.encl, env));
            clazzid1 = make.at(clazz.pos).Select(make.Type(encltype),
                    ((Ident) clazzid).name);
            clazz = clazzid1;
        }
        Type clazztype = chk.checkClassType(tree.clazz.pos, attribType(clazz, env));
        chk.validate(clazz);
        if (tree.encl != null) {
            tree.clazz.type = clazztype;
            TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1));
            clazzid.type = ((Ident) clazzid).sym.type;
            if ((clazztype.tsym.flags() & STATIC) != 0 && !clazztype.isErroneous()) {
                log.error(tree.pos, "qualified.new.of.static.class",
                        clazztype.tsym.toJava());
            }
        } else if ((clazztype.tsym.flags() & INTERFACE) == 0 &&
                clazztype.outer().tag == CLASS) {
            rs.resolveImplicitThis(tree.pos, env, clazztype);
        }
        List argtypes = attribArgs(tree.args, env);
        if (clazztype.tag == CLASS) {
            if (cdef == null &&
                    (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
                log.error(tree.pos, "abstract.cant.be.instantiated",
                        clazztype.tsym.toJava());
            } else if (cdef != null && (clazztype.tsym.flags() & INTERFACE) != 0) {
                if (argtypes.nonEmpty()) {
                    log.error(tree.pos, "anon.class.impl.intf.no.args");
                    argtypes = Type.emptyList;
                } else if (tree.encl != null) {
                    log.error(tree.pos, "anon.class.impl.intf.no.qual.for.new");
                }
            } else {
                boolean selectSuperPrev = ((AttrContext) env.info).selectSuper;
                if (cdef != null)
                    ((AttrContext) env.info).selectSuper = true;
                tree.constructor =
                        rs.resolveConstructor(tree.pos, env, clazztype, argtypes);
                ((AttrContext) env.info).selectSuper = selectSuperPrev;
            }
            if (cdef != null) {
                if (Resolve.isStatic(env))
                    cdef.flags |= STATIC;
                if ((clazztype.tsym.flags() & INTERFACE) != 0) {
                    cdef.implementing = List.make(clazz);
                } else {
                    cdef.extending = clazz;
                }
                attribStat(cdef, env.dup(tree));
                if (tree.encl != null) {
                    tree.args = tree.args.prepend(makeNullCheck(tree.encl));
                    argtypes = argtypes.prepend(tree.encl.type);
                    tree.encl = null;
                }
                clazztype = cdef.sym.type;
                tree.constructor =
                        rs.resolveConstructor(tree.pos, env, clazztype, argtypes);
            }
            if (tree.constructor != null && tree.constructor.kind == MTH) {
                owntype = clazztype;
            }
        }
        result = check(tree, owntype, VAL, pkind, pt);
    }

    /**
      * Make an attributed null check tree.
      */
    public Tree makeNullCheck(Tree arg) {
        Name name = TreeInfo.name(arg);
        if (name == names._this || name == names._super)
            return arg;
        int optag = Tree.NULLCHK;
        Unary tree = make.at(arg.pos).Unary(optag, arg);
        tree.operator = syms.nullcheck;
        tree.type = arg.type;
        return tree;
    }

    public void visitNewArray(NewArray tree) {
        Type owntype = syms.errType;
        Type elemtype;
        if (tree.elemtype != null) {
            elemtype = attribType(tree.elemtype, env);
            chk.validate(tree.elemtype);
            owntype = elemtype;
            for (List l = tree.dims; l.nonEmpty(); l = l.tail) {
                attribExpr((Tree) l.head, env, syms.intType);
                owntype = new ArrayType(owntype, syms.arrayClass);
            }
        } else {
            if (pt.tag == ARRAY) {
                elemtype = pt.elemtype();
            } else {
                if (pt.tag != ERROR) {
                    log.error(tree.pos, "illegal.initializer.for.type", pt.toJava());
                }
                elemtype = syms.errType;
            }
        }
        if (tree.elems != null) {
            attribExprs(tree.elems, env, elemtype);
            owntype = new ArrayType(elemtype, syms.arrayClass);
        }
        result = check(tree, owntype, VAL, pkind, pt);
    }

    public void visitParens(Parens tree) {
        Type owntype = attribTree(tree.expr, env, pkind, pt);
        result = check(tree, owntype, pkind, pkind, pt);
        Symbol sym = TreeInfo.symbol(tree);
        if (isType(sym)) {
            log.error(tree.pos, "illegal.start.of.expr");
        }
    }

    public void visitAssign(Assign tree) {
        Type owntype = attribTree(tree.lhs, env.dup(tree), VAR, pt);
        attribExpr(tree.rhs, env, owntype);
        result = check(tree, owntype, VAL, pkind, pt);
    }

    public void visitAssignop(Assignop tree) {
        List argtypes = List.make(attribTree(tree.lhs, env, VAR, Type.noType),
                attribExpr(tree.rhs, env));
        Symbol operator = tree.operator =
                rs.resolveOperator(tree.pos, tree.tag - Tree.ASGOffset, env,
                argtypes);
        Type owntype = (Type) argtypes.head;
        if (operator.kind == MTH) {
            if (owntype.tag <= DOUBLE)
                chk.checkCastable(tree.rhs.pos, operator.type.restype(), owntype);
            else if (owntype.tag == CLASS)
                chk.checkType(tree.lhs.pos, owntype, syms.stringType);
            else
                chk.checkType(tree.rhs.pos, operator.type.restype(), owntype);
        }
        result = check(tree, owntype, VAL, pkind, pt);
    }

    public void visitUnary(Unary tree) {
        Type argtype = (Tree.PREINC <= tree.tag && tree.tag <= Tree.POSTDEC) ?
                attribTree(tree.arg, env, VAR, Type.noType) :
                chk.checkNonVoid(tree.arg.pos, attribExpr(tree.arg, env));
        Symbol operator = tree.operator =
                rs.resolveUnaryOperator(tree.pos, tree.tag, env, argtype);
        Type owntype = syms.errType;
        if (operator.kind == MTH) {
            owntype = operator.type.restype();
            int opc = ((OperatorSymbol) operator).opcode;
            if (argtype.constValue != null) {
                Type ctype = cfolder.fold1(opc, argtype);
                if (ctype != null) {
                    owntype = cfolder.coerce(ctype, owntype);
                    if (tree.arg.type.tsym == syms.stringType.tsym) {
                        tree.arg.type = syms.stringType;
                    }
                }
            }
        }
        result = check(tree, owntype, VAL, pkind, pt);
    }

    public void visitBinary(Binary tree) {
        Type left = chk.checkNonVoid(tree.lhs.pos, attribExpr(tree.lhs, env));
        Type right = chk.checkNonVoid(tree.lhs.pos, attribExpr(tree.rhs, env));
        Symbol operator = tree.operator =
                rs.resolveBinaryOperator(tree.pos, tree.tag, env, left, right);
        Type owntype = syms.errType;
        if (operator.kind == MTH) {
            owntype = operator.type.restype();
            int opc = ((OperatorSymbol) operator).opcode;
            if (opc == ByteCodes.error) {
                log.error(tree.lhs.pos, "operator.cant.be.applied",
                        treeinfo.operatorName(tree.tag).toJava(),
                        left.toJava() + "," + right.toJava());
            }
            if (left.constValue != null && right.constValue != null) {
                Type ctype = cfolder.fold2(opc, left, right);
                if (ctype != null) {
                    owntype = cfolder.coerce(ctype, owntype);
                    if (tree.lhs.type.tsym == syms.stringType.tsym) {
                        tree.lhs.type = syms.stringType;
                    }
                    if (tree.rhs.type.tsym == syms.stringType.tsym) {
                        tree.rhs.type = syms.stringType;
                    }
                }
            }
            if (opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne) {
                if (!left.isCastable(right.erasure()) &&
                        !right.isCastable(left.erasure())) {
                    log.error(tree.pos, "incomparable.types", left.toJava(),
                            right.toJava());
                } else {
                    chk.checkCompatible(tree.pos, left, right);
                }
            }
        }
        result = check(tree, owntype, VAL, pkind, pt);
    }

    public void visitTypeCast(TypeCast tree) {
        Type clazztype = attribType(tree.clazz, env);
        Type exprtype = attribExpr(tree.expr, env, Type.noType);
        Type owntype = chk.checkCastable(tree.expr.pos, exprtype, clazztype);
        if (exprtype.constValue != null)
            owntype = cfolder.coerce(exprtype, owntype);
        result = check(tree, owntype, VAL, pkind, pt);
    }

    public void visitTypeTest(TypeTest tree) {
        Type exprtype = attribExpr(tree.expr, env);
        Type clazztype = chk.checkClassOrArrayType(tree.clazz.pos,
                attribType(tree.clazz, env));
        chk.checkCastable(tree.expr.pos, exprtype, clazztype);
        result = check(tree, syms.booleanType, VAL, pkind, pt);
    }

    public void visitIndexed(Indexed tree) {
        Type owntype = syms.errType;
        Type atype = attribExpr(tree.indexed, env);
        attribExpr(tree.index, env, syms.intType);
        if (atype.tag == ARRAY)
            owntype = atype.elemtype();
        else if (atype.tag != ERROR)
            log.error(tree.pos, "array.req.but.found", atype.toJava());
        result = check(tree, owntype, VAR, pkind, pt);
    }

    public void visitIdent(Ident tree) {
        Symbol sym;
        if (pt.tag == METHOD) {
            sym = rs.resolveMethod(tree.pos, env, tree.name, pt.argtypes());
        } else if (tree.sym != null && tree.sym.kind != VAR) {
            sym = tree.sym;
        } else {
            sym = rs.resolveIdent(tree.pos, env, tree.name, pkind);
        }
        tree.sym = sym;
        Env symEnv = env;
        boolean noOuterThisPath = false;
        if (env.enclClass.sym.owner.kind != PCK &&
                (sym.kind & (VAR | MTH | TYP)) != 0 && sym.owner.kind == TYP &&
                tree.name != names._this && tree.name != names._super) {
            while (symEnv.outer != null && !sym.isMemberOf(symEnv.enclClass.sym)) {
                if ((symEnv.enclClass.sym.flags() & NOOUTERTHIS) != 0)
                    noOuterThisPath = true;
                symEnv = symEnv.outer;
            }
        }
        if (sym.kind == VAR) {
            VarSymbol v = (VarSymbol) sym;
            checkInit(tree, env, v);
            if (v.owner.kind == MTH &&
                    v.owner != ((AttrContext) env.info).scope.owner) {
                if ((v.flags_field & FINAL) == 0) {
                    log.error(tree.pos, "local.var.accessed.from.icls.needs.final",
                            v.toJava());
                }
            }
            if (pkind == VAR)

⌨️ 快捷键说明

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