    001    /* Copyright 2000, 2001, Compaq Computer Corporation */
    002
    003    package javafe.tc;
    004
    005    import javafe.ast.*;
    006    import javafe.util.*;
    007
    008
    009    /**
    010     * This class is responsible for transitioning TypeSigs to the
    011     * LINKSRESOLVED state from an earlier state.<p>
    012     *
    013     *
    014     * So transitioning sig involves the following:
    015     *
    016     *   (1) Ensuring that sig's CompilationUnit is checked.  (See
    017     *       CheckCompilationUnit)
    018     *
    019     *   (2) Resolving all sig's supertype names (see
    020     *       Env.resolveTypeName); these are the names mentioned in sig's
    021     *       TypeDecl's extends and implements clauses (if any).
    022     *
    023     *   (3) Handling missing extends clauses for classes appropriately
    024     *       (E.g., inserting a reference to java.lang.Object, or null if (4))
    025     *
    026     *   (4) If sig is java.lang.Object, then we always set its superClass
    027     *       field to null.  We check to make sure that the user did
    028     *       not try to make us extend a class other than us.
    029     *
    030     *   (5) Transitioning all of sig's direct supertypes (the types
    031     *       resolved above) to at least the LINKSRESOLVED state.
    032     *
    033     *   (6) Detecting loops in the inheritance/enclosing graph that
    034     *       would otherwise cause (5) to hang.
    035     *
    036     * It is a fatal error if we cannot resolve a supertype name or if we
    037     * detect a cycle.
    038     *
    039     *
    040     * Notes:
    041     *
    042     *   - Checking whether sig's direct supertypes are accessible from sig
    043     *     is now done by the "prepping" stage.  (This is necessary
    044     *     because access checking requires calling isSubTypeOf.)
    045     *
    046     *   - No TypeSig is ever advanced beyond LINKSRESOLVED by this
    047     *     process.  This fact depends on the control flow elsewhere in the
    048     *     javafe.tc package.  In particular, Env.resolveTypeName obeys
    049     *     this requirement.
    050     *
    051     *   - Exactly which TypeSigs will be moved to at least the
    052     *     LINKSRESOLVED stage is tricky to compute in advance because
    053     *     TypeName resolution may itself require enclosing TypeSigs to be
    054     *     transitioned to at least the LINKSRESOLVED stage.
    055     *
    056     *   - In general, we try to transition to smallest number of
    057     *     TypeSigs we can to maximize the number of legal programs.
    058     *     (results in fewer cycles detected.)
    059     *
    060     * @see TypeSig
    061     * @see Env
    062     * @see CheckCompilationUnit
    063     */
    064
    065    public class SLResolution {
    066
    067        /**
    068         * Transition <code>sig</code> to the supertype-links-resolved
    069         * state. <p>
    070         *
    071         * See the SLResolution type's overall comments for details of
    072         * what this involves.<p>
    073         *
    074         * A fatal error may be reported if we cannot resolve a supertype
    075         * name, or detect a cycle in the type hierarchy.<p>
    076         */
    077        //@ requires sig.state < TypeSig.LINKSRESOLVED;
    078        //@ modifies sig.state;
    079        //@ ensures sig.state==TypeSig.LINKSRESOLVED;
    080        /*package*/ public static void transition(/*@ non_null @*/ TypeSig sig) {
    081            /*
    082             * First, check to see if we've looped:
    083             */
    084            TypeDecl d = sig.getTypeDecl();
    085            if (sig.state==TypeSig.RESOLVINGLINKS)
    086                ErrorSet.fatal(d.locId,
    087                               "Cycle in inheritance/enclosing hierarchy "
    088                               + "detected involving type " + sig);
    089
    090            Info.out("[Superlink resolving " + sig + "]");
    091            sig.state = TypeSig.RESOLVINGLINKS;
    092
    093
    094            /*
    095             * Do CompilationUnit-level checks first to make sure that
    096             * import statements are ok:
    097             */
    098            CheckCompilationUnit.checkCompilationUnit(sig.getCompilationUnit());
    099
    100
    101            /*
    102             * Call handleSuperTypeName on each of our supertype names.
    103             *
    104             * Fixup a null superclass pointer into a reference to
    105             * java.lang.Object unless sig is java.lang.Object.
    106             */
    107            for (int i=0; i<d.superInterfaces.size(); i++)
    108                handleSuperTypeName(sig, d.superInterfaces.elementAt(i));
    109
    110            if (d.getTag() == TagConstants.CLASSDECL) {
    111                ClassDecl cd = (ClassDecl)d;
    112
    113                if (cd.superClass==null) {
    114                    cd.superClass = TypeName.make(Name.make(//@ nowarn Pre;//strlen
    115                                                            "java.lang.Object",
    116                                                            cd.locOpenBrace));
    117                    TypeSig.setSig(cd.superClass, Types.javaLangObject());
    118                }
    119
    120                TypeSig superClass = handleSuperTypeName(sig, cd.superClass);
    121
    122                // Handle java.lang.Object specially:
    123                if (sig==Types.javaLangObject()) {
    124                    if (superClass != sig)
    125                        ErrorSet.fatal(d.loc, "Only java.lang.Object may be "
    126                                       + "the superclass of java.lang.Object");
    127
    128                    // Leave TypeDecl in canonical form:
    129                    cd.superClass = null;
    130                }
    131            }
    132
    133            Info.out("[Superlink resolved " + sig + "]");
    134            sig.state = TypeSig.LINKSRESOLVED;
    135        }
    136
    137
    138        /**
    139         * Handle a super type name. <p>
    140         *
    141         * We resolve the typename (a fatal error results if we cannot)
    142         * then transition the resulting type to at least the
    143         * LINKSRESOLVED stage.  We return the TypeSig for the
    144         * supertype.<p>
    145         *
    146         * sig is the TypeSig that superName names a supertype for.<p>
    147         *
    148         * Exception: if sig is java.lang.Object, then we do not try and
    149         * transition its superclass.<p>
    150         */
    151        public static TypeSig handleSuperTypeName(
    152                                   /*@ non_null @*/ TypeSig sig,
    153                                   /*@ non_null @*/ TypeName superName) {
    154            TypeSig supertype = sig.getEnclosingEnv().resolveTypeName(null,superName);
    155
    156            if (supertype.state < TypeSig.LINKSRESOLVED &&
    157                sig != Types.javaLangObject())
    158                transition(supertype);
    159
    160            return supertype;
    161        }
    162    }