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    }