1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Sat Sep 18 09:56:23 2010 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Sat Sep 18 14:24:09 2010 -0700 1.3 @@ -60,6 +60,7 @@ 1.4 private final Names names; 1.5 private final Log log; 1.6 private final Symtab syms; 1.7 + private final Enter enter; 1.8 private final Infer infer; 1.9 private final Types types; 1.10 private final JCDiagnostic.Factory diags; 1.11 @@ -86,6 +87,7 @@ 1.12 names = Names.instance(context); 1.13 log = Log.instance(context); 1.14 syms = Symtab.instance(context); 1.15 + enter = Enter.instance(context); 1.16 infer = Infer.instance(context); 1.17 this.types = Types.instance(context); 1.18 diags = JCDiagnostic.Factory.instance(context); 1.19 @@ -1727,6 +1729,113 @@ 1.20 return undef; 1.21 } 1.22 1.23 + void checkNonCyclicDecl(JCClassDecl tree) { 1.24 + CycleChecker cc = new CycleChecker(); 1.25 + cc.scan(tree); 1.26 + if (!cc.errorFound && !cc.partialCheck) { 1.27 + tree.sym.flags_field |= ACYCLIC; 1.28 + } 1.29 + } 1.30 + 1.31 + class CycleChecker extends TreeScanner { 1.32 + 1.33 + List<Symbol> seenClasses = List.nil(); 1.34 + boolean errorFound = false; 1.35 + boolean partialCheck = false; 1.36 + 1.37 + private void checkSymbol(DiagnosticPosition pos, Symbol sym) { 1.38 + if (sym != null && sym.kind == TYP) { 1.39 + Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym); 1.40 + if (classEnv != null) { 1.41 + DiagnosticSource prevSource = log.currentSource(); 1.42 + try { 1.43 + log.useSource(classEnv.toplevel.sourcefile); 1.44 + scan(classEnv.tree); 1.45 + } 1.46 + finally { 1.47 + log.useSource(prevSource.getFile()); 1.48 + } 1.49 + } else if (sym.kind == TYP) { 1.50 + checkClass(pos, sym, List.<JCTree>nil()); 1.51 + } 1.52 + } else { 1.53 + //not completed yet 1.54 + partialCheck = true; 1.55 + } 1.56 + } 1.57 + 1.58 + @Override 1.59 + public void visitSelect(JCFieldAccess tree) { 1.60 + super.visitSelect(tree); 1.61 + checkSymbol(tree.pos(), tree.sym); 1.62 + } 1.63 + 1.64 + @Override 1.65 + public void visitIdent(JCIdent tree) { 1.66 + checkSymbol(tree.pos(), tree.sym); 1.67 + } 1.68 + 1.69 + @Override 1.70 + public void visitTypeApply(JCTypeApply tree) { 1.71 + scan(tree.clazz); 1.72 + } 1.73 + 1.74 + @Override 1.75 + public void visitTypeArray(JCArrayTypeTree tree) { 1.76 + scan(tree.elemtype); 1.77 + } 1.78 + 1.79 + @Override 1.80 + public void visitClassDef(JCClassDecl tree) { 1.81 + List<JCTree> supertypes = List.nil(); 1.82 + if (tree.getExtendsClause() != null) { 1.83 + supertypes = supertypes.prepend(tree.getExtendsClause()); 1.84 + } 1.85 + if (tree.getImplementsClause() != null) { 1.86 + for (JCTree intf : tree.getImplementsClause()) { 1.87 + supertypes = supertypes.prepend(intf); 1.88 + } 1.89 + } 1.90 + checkClass(tree.pos(), tree.sym, supertypes); 1.91 + } 1.92 + 1.93 + void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) { 1.94 + if ((c.flags_field & ACYCLIC) != 0) 1.95 + return; 1.96 + if (seenClasses.contains(c)) { 1.97 + errorFound = true; 1.98 + noteCyclic(pos, (ClassSymbol)c); 1.99 + } else if (!c.type.isErroneous()) { 1.100 + try { 1.101 + seenClasses = seenClasses.prepend(c); 1.102 + if (c.type.tag == CLASS) { 1.103 + if (supertypes.nonEmpty()) { 1.104 + scan(supertypes); 1.105 + } 1.106 + else { 1.107 + ClassType ct = (ClassType)c.type; 1.108 + if (ct.supertype_field == null || 1.109 + ct.interfaces_field == null) { 1.110 + //not completed yet 1.111 + partialCheck = true; 1.112 + return; 1.113 + } 1.114 + checkSymbol(pos, ct.supertype_field.tsym); 1.115 + for (Type intf : ct.interfaces_field) { 1.116 + checkSymbol(pos, intf.tsym); 1.117 + } 1.118 + } 1.119 + if (c.owner.kind == TYP) { 1.120 + checkSymbol(pos, c.owner); 1.121 + } 1.122 + } 1.123 + } finally { 1.124 + seenClasses = seenClasses.tail; 1.125 + } 1.126 + } 1.127 + } 1.128 + } 1.129 + 1.130 /** Check for cyclic references. Issue an error if the 1.131 * symbol of the type referred to has a LOCKED flag set. 1.132 *