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 }