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 }