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

📄 attr.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/**
 * @(#)Attr.java	1.93 03/01/23
 *
 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.sun.tools.javac.v8.comp;
import com.sun.tools.javac.v8.util.*;

import com.sun.tools.javac.v8.code.*;

import com.sun.tools.javac.v8.tree.*;

import com.sun.tools.javac.v8.code.Symbol.*;

import com.sun.tools.javac.v8.tree.Tree.*;

import com.sun.tools.javac.v8.code.Type.*;


/**
 * This is the main context-dependent analysis phase in GJC. It
 *  encompasses name resolution, type checking and constant folding as
 *  subtasks. Some subtasks involve auxiliary classes.
 *  @see Check
 *  @see Resolve
 *  @see ConstFold
 *  @see Infer
 */
public class Attr extends Tree.Visitor implements Flags, Kinds, TypeTags {
    private static final Context.Key attrKey = new Context.Key();
    private Name.Table names;
    private Log log;
    private Symtab syms;
    private Resolve rs;
    private Check chk;
    private TreeMaker make;
    private ConstFold cfolder;
    private Enter enter;
    private TreeInfo treeinfo;
    private Target target;

    public static Attr instance(Context context) {
        Attr instance = (Attr) context.get(attrKey);
        if (instance == null)
            instance = new Attr(context);
        return instance;
    }

    private Attr(Context context) {
        super();
        context.put(attrKey, this);
        names = Name.Table.instance(context);
        log = Log.instance(context);
        syms = Symtab.instance(context);
        rs = Resolve.instance(context);
        chk = Check.instance(context);
        make = TreeMaker.instance(context);
        enter = Enter.instance(context);
        cfolder = ConstFold.instance(context);
        treeinfo = TreeInfo.instance(context);
        target = Target.instance(context);
        Options options = Options.instance(context);
        retrofit = options.get("-retrofit") != null;
    }

    /**
      * Switch: retrofit mode?
      */
    boolean retrofit;

    /**
     * Check kind and type of given tree against protokind and prototype.
     *  If check succeeds, store type in tree and return it.
     *  If check fails, store errType in tree and return it.
     *  No checks are performed if the prototype is a method type.
     *  Its not necessary in this case since we know that kind and type
     *  are correct.
     *
     *  @param tree     The tree whose kind and type is checked
     *  @param owntype  The computed type of the tree
     *  @param ownkind  The computed kind of the tree
     *  @param pkind    The expected kind (or: protokind) of the tree
     *  @param pt       The expected type (or: prototype) of the tree
     */
    Type check(Tree tree, Type owntype, int ownkind, int pkind, Type pt) {
        if (owntype.tag != ERROR && pt.tag != METHOD) {
            if ((ownkind & ~pkind) == 0) {
                owntype = chk.checkType(tree.pos, owntype, pt);
            } else {
                log.error(tree.pos, "unexpected.type", Resolve.kindNames(pkind),
                        Resolve.kindName(ownkind));
                owntype = syms.errType;
            }
        }
        tree.type = owntype;
        return owntype;
    }

    /**
      * Is given blank final variable assignable, i.e. in a scope where it
      *  may be assigned to even though it is final?
      *  @param v      The blank final variable.
      *  @param env    The current environment.
      */
    boolean isAssignableAsBlankFinal(VarSymbol v, Env env) {
        Symbol owner = ((AttrContext) env.info).scope.owner;
        return v.owner == owner || ((owner.name == names.init || owner.kind == VAR ||
                (owner.flags() & BLOCK) != 0) && v.owner == owner.owner &&
                ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));
    }

    /**
      * Check that variable can be assigned to.
      *  @param pos    The current source code position.
      *  @param v      The assigned varaible
      *  @param base   If the variable is referred to in a Select, the part
      *                to the left of the `.', null otherwise.
      *  @env          The current environment.
      */
    void checkAssignable(int pos, VarSymbol v, Tree base, Env env) {
        if ((v.flags() & FINAL) != 0 && ((v.flags() & HASINIT) != 0 ||
                !((base == null ||
                (base.tag == Tree.IDENT && TreeInfo.name(base) == names._this))
                && isAssignableAsBlankFinal(v, env)))) {
            log.error(pos, "cant.assign.val.to.final.var", v.toJava());
        }
    }

    /**
      * Does tree represent a static reference to an identifier?
      *  It is assumed that tree is either a SELECT or an IDENT.
      *  We have to weed out selects from non-type names here.
      *  @param tree    The candidate tree.
      */
    boolean isStaticReference(Tree tree) {
        if (tree.tag == Tree.SELECT) {
            Symbol lsym = TreeInfo.symbol(((Select) tree).selected);
            if (lsym == null || lsym.kind != TYP) {
                return false;
            }
        }
        return true;
    }

    /**
      * Is this symbol a type?
      */
    static boolean isType(Symbol sym) {
        return sym != null && sym.kind == TYP;
    }

    /**
      * The current `this' symbol.
      *  @param env    The current environment.
      */
    Symbol thisSym(Env env) {
        return rs.resolveSelf(Position.NOPOS, env, env.enclClass.sym, names._this);
    }

    /**
      * Visitor argument: the current environment.
      */
    Env env;

    /**
     * Visitor argument: the currently expected proto-kind.
     */
    int pkind;

    /**
     * Visitor argument: the currently expected proto-type.
     */
    Type pt;

    /**
     * Visitor result: the computed type.
     */
    Type result;

    /**
     * Visitor method: attribute a tree, catching any completion failure
     *  exceptions. Return the tree's type.
     *
     *  @param tree    The tree to be visited.
     *  @param env     The environment visitor argument.
     *  @param pkind   The protokind visitor argument.
     *  @param pt      The prototype visitor argument.
     */
    Type attribTree(Tree tree, Env env, int pkind, Type pt) {
        Env prevEnv = this.env;
        int prevPkind = this.pkind;
        Type prevPt = this.pt;
        try {
            this.env = env;
            this.pkind = pkind;
            this.pt = pt;
            tree.accept(this);
            return result;
        } catch (CompletionFailure ex) {
            tree.type = syms.errType;
            return chk.completionError(tree.pos, ex);
        }
        finally { this.env = prevEnv;
                  this.pkind = prevPkind;
                  this.pt = prevPt;
                } }

    /**
      * Derived visitor method: attribute an expression tree.
      */
    Type attribExpr(Tree tree, Env env, Type pt) {
        return attribTree(tree, env, VAL, pt);
    }

    /**
      * Derived visitor method: attribute an expression tree with
      *  no constraints on the computed type.
      */
    Type attribExpr(Tree tree, Env env) {
        return attribTree(tree, env, VAL, Type.noType);
    }

    /**
      * Derived visitor method: attribute a type tree.
      */
    Type attribType(Tree tree, Env env) {
        return attribTree(tree, env, TYP, Type.noType);
    }

    /**
      * Derived visitor method: attribute a statement or definition tree.
      */
    Type attribStat(Tree tree, Env env) {
        return attribTree(tree, env, NIL, Type.noType);
    }

    /**
      * Attribute a list of expressions, returning a list of types.
      */
    List attribExprs(List trees, Env env, Type pt) {
        ListBuffer ts = new ListBuffer();
        for (List l = trees; l.nonEmpty(); l = l.tail)
            ts.append(attribExpr((Tree) l.head, env, pt));
        return ts.toList();
    }

    /**
      * Attribute a list of statements, returning nothing.
      */
    void attribStats(List trees, Env env) {
        for (List l = trees; l.nonEmpty(); l = l.tail)
            attribStat((Tree) l.head, env);
    }

    /**
      * Attribute the arguments in a method call, returning a list of types.
      */
    List attribArgs(List trees, Env env) {
        ListBuffer argtypes = new ListBuffer();
        for (List l = trees; l.nonEmpty(); l = l.tail)
            argtypes.append( chk.checkNonVoid(((Tree) l.head).pos,
                    attribTree((Tree) l.head, env, VAL, Infer.anyPoly)));
        return argtypes.toList();
    }

    /**
      * Attribute type reference in an `extends' or `implements' clause.
      *
      *  @param tree              The tree making up the type reference.
      *  @param env               The environment current at the reference.
      *  @param classExpected     true if only a class is expected here.
      *  @param interfaceExpected true if only an interface is expected here.
      */
    Type attribBase(Tree tree, Env env, boolean classExpected,
            boolean interfaceExpected) {
        Type t = attribType(tree, env);
        t = chk.checkClassType(tree.pos, t);
        if (interfaceExpected & (t.tsym.flags() & INTERFACE) == 0) {
            log.error(tree.pos, "intf.expected.here");
            return syms.errType;
        } else if (classExpected & (t.tsym.flags() & INTERFACE) != 0) {
            log.error(tree.pos, "no.intf.expected.here");
            return syms.errType;
        }
        if ((t.tsym.flags() & FINAL) != 0) {
            log.error(tree.pos, "cant.inherit.from.final", t.tsym.toJava());
        }
        return t;
    }

    public void visitClassDef(ClassDef tree) {
        if ((((AttrContext) env.info).scope.owner.kind & (VAR | MTH)) != 0)
            enter.classEnter(tree, env);
        ClassSymbol c = tree.sym;
        if (c == null) {
            result = null;
        } else {
            c.complete();
            if (((AttrContext) env.info).isSelfCall &&
                    env.tree.tag == Tree.NEWCLASS &&
                    ((NewClass) env.tree).encl == null) {
                c.flags_field |= NOOUTERTHIS;
            }
            attribClass(tree.pos, c);
            result = tree.type = c.type;
        }
    }

    public void visitMethodDef(MethodDef tree) {
        MethodSymbol m = tree.sym;
        chk.checkOverride(tree, m);
        Env localEnv = enter.methodEnv((MethodDef) tree, env);
        for (List l = tree.params; l.nonEmpty(); l = l.tail)
            attribStat((Tree) l.head, localEnv);
        chk.validate(tree.restype);
        for (List l = tree.thrown; l.nonEmpty(); l = l.tail)
            chk.checkType(((Tree) l.head).pos, ((Tree) l.head).type,
                    syms.throwableType);
        ClassSymbol owner = env.enclClass.sym;
        if (tree.body == null) {
            if ((owner.flags() & INTERFACE) == 0 &&
                    (tree.flags & (ABSTRACT | NATIVE)) == 0 && !retrofit)
                log.error(tree.pos, "missing.meth.body.or.decl.abstract");
        } else if ((owner.flags() & INTERFACE) != 0) {
            log.error(tree.body.pos, "intf.meth.cant.have.body");
        } else if ((tree.flags & ABSTRACT) != 0) {
            log.error(tree.pos, "abstract.meth.cant.have.body");
        } else if ((tree.flags & NATIVE) != 0) {
            log.error(tree.pos, "native.meth.cant.have.body");
        } else {
            if (tree.name == names.init && owner.type != syms.objectType) {
                Block body = tree.body;
                if (body.stats.isEmpty() ||
                        !TreeInfo.isSelfCall((Tree) body.stats.head)) {
                    body.stats = body.stats.prepend(
                            enter.SuperCall(make.at(body.pos), VarDef.emptyList,
                            false));
                }
            }
            attribStat(tree.body, localEnv);
        }
        ((AttrContext) localEnv.info).scope.leave();
        result = tree.type = m.type;
    }

    public void visitVarDef(VarDef tree) {
        if (((AttrContext) env.info).scope.owner.kind == MTH)
            enter.phase2.memberEnter(tree, env);

⌨️ 快捷键说明

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