langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 25443 9187d77f2c64
parent 25301 e5da086c7d43
child 25445 603f0c93d5c9
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Jul 08 18:26:34 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jul 09 16:32:05 2014 +0200
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.Compound;
@@ -39,6 +40,8 @@
 
 import com.sun.tools.javac.code.Lint;
 import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.code.Scope.NamedImportScope;
+import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
@@ -51,6 +54,7 @@
 import static com.sun.tools.javac.code.Flags.ANNOTATION;
 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED;
 import static com.sun.tools.javac.code.Kinds.*;
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.code.TypeTag.WILDCARD;
 
@@ -362,16 +366,13 @@
      *  @param s             The scope.
      */
     void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) {
-        if (s.next != null) {
-            for (Scope.Entry e = s.next.lookup(v.name);
-                 e.scope != null && e.sym.owner == v.owner;
-                 e = e.next()) {
-                if (e.sym.kind == VAR &&
-                    (e.sym.owner.kind & (VAR | MTH)) != 0 &&
-                    v.name != names.error) {
-                    duplicateError(pos, e.sym);
-                    return;
-                }
+        for (Symbol sym : s.getSymbolsByName(v.name)) {
+            if (sym.owner != v.owner) break;
+            if (sym.kind == VAR &&
+                (sym.owner.kind & (VAR | MTH)) != 0 &&
+                v.name != names.error) {
+                duplicateError(pos, sym);
+                return;
             }
         }
     }
@@ -383,16 +384,13 @@
      *  @param s             The scope.
      */
     void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) {
-        if (s.next != null) {
-            for (Scope.Entry e = s.next.lookup(c.name);
-                 e.scope != null && e.sym.owner == c.owner;
-                 e = e.next()) {
-                if (e.sym.kind == TYP && !e.sym.type.hasTag(TYPEVAR) &&
-                    (e.sym.owner.kind & (VAR | MTH)) != 0 &&
-                    c.name != names.error) {
-                    duplicateError(pos, e.sym);
-                    return;
-                }
+        for (Symbol sym : s.getSymbolsByName(c.name)) {
+            if (sym.owner != c.owner) break;
+            if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR) &&
+                (sym.owner.kind & (VAR | MTH)) != 0 &&
+                c.name != names.error) {
+                duplicateError(pos, sym);
+                return;
             }
         }
     }
@@ -405,9 +403,9 @@
      *  @param s             The enclosing scope.
      */
     boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) {
-        for (Scope.Entry e = s.lookup(name); e.scope == s; e = e.next()) {
-            if (e.sym.kind == TYP && e.sym.name != names.error) {
-                duplicateError(pos, e.sym);
+        for (Symbol sym : s.getSymbolsByName(name, NON_RECURSIVE)) {
+            if (sym.kind == TYP && sym.name != names.error) {
+                duplicateError(pos, sym);
                 return false;
             }
         }
@@ -1778,10 +1776,7 @@
         for (Type t1 = sup;
              t1.hasTag(CLASS) && t1.tsym.type.isParameterized();
              t1 = types.supertype(t1)) {
-            for (Scope.Entry e1 = t1.tsym.members().elems;
-                 e1 != null;
-                 e1 = e1.sibling) {
-                Symbol s1 = e1.sym;
+            for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) {
                 if (s1.kind != MTH ||
                     (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
                     !s1.isInheritedIn(site.tsym, types) ||
@@ -1796,10 +1791,7 @@
                 for (Type t2 = sup;
                      t2.hasTag(CLASS);
                      t2 = types.supertype(t2)) {
-                    for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name);
-                         e2.scope != null;
-                         e2 = e2.next()) {
-                        Symbol s2 = e2.sym;
+                    for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) {
                         if (s2 == s1 ||
                             s2.kind != MTH ||
                             (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
@@ -1893,15 +1885,13 @@
 
     /** Return the first method in t2 that conflicts with a method from t1. */
     private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
-        for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) {
-            Symbol s1 = e1.sym;
+        for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) {
             Type st1 = null;
             if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) ||
                     (s1.flags() & SYNTHETIC) != 0) continue;
             Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false);
             if (impl != null && (impl.flags() & ABSTRACT) == 0) continue;
-            for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) {
-                Symbol s2 = e2.sym;
+            for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) {
                 if (s1 == s2) continue;
                 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) ||
                         (s2.flags() & SYNTHETIC) != 0) continue;
@@ -1944,8 +1934,7 @@
         Type st2 = types.memberType(site, s2);
         closure(site, supertypes);
         for (Type t : supertypes.values()) {
-            for (Scope.Entry e = t.tsym.members().lookup(s1.name); e.scope != null; e = e.next()) {
-                Symbol s3 = e.sym;
+            for (Symbol s3 : t.tsym.members().getSymbolsByName(s1.name)) {
                 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue;
                 Type st3 = types.memberType(site,s3);
                 if (types.overrideEquivalent(st3, st1) &&
@@ -1995,14 +1984,12 @@
 
     void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) {
         TypeSymbol c = site.tsym;
-        Scope.Entry e = c.members().lookup(m.name);
-        while (e.scope != null) {
-            if (m.overrides(e.sym, origin, types, false)) {
-                if ((e.sym.flags() & ABSTRACT) == 0) {
-                    checkOverride(tree, m, (MethodSymbol)e.sym, origin);
+        for (Symbol sym : c.members().getSymbolsByName(m.name)) {
+            if (m.overrides(sym, origin, types, false)) {
+                if ((sym.flags() & ABSTRACT) == 0) {
+                    checkOverride(tree, m, (MethodSymbol)sym, origin);
                 }
             }
-            e = e.next();
         }
     }
 
@@ -2037,9 +2024,9 @@
             ClassSymbol someClass) {
         if (lint.isEnabled(LintCategory.OVERRIDES)) {
             MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType
-                    .tsym.members().lookup(names.equals).sym;
+                    .tsym.members().findFirst(names.equals);
             MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType
-                    .tsym.members().lookup(names.hashCode).sym;
+                    .tsym.members().findFirst(names.hashCode);
             boolean overridesEquals = types.implementation(equalsAtObject,
                 someClass, false, equalsHasCodeFilter).owner == someClass;
             boolean overridesHashCode = types.implementation(hashCodeAtObject,
@@ -2095,12 +2082,10 @@
             // since they cannot have abstract members.
             if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
                 Scope s = c.members();
-                for (Scope.Entry e = s.elems;
-                     undef == null && e != null;
-                     e = e.sibling) {
-                    if (e.sym.kind == MTH &&
-                        (e.sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
-                        MethodSymbol absmeth = (MethodSymbol)e.sym;
+                for (Symbol sym : s.getSymbols(NON_RECURSIVE)) {
+                    if (sym.kind == MTH &&
+                        (sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) {
+                        MethodSymbol absmeth = (MethodSymbol)sym;
                         MethodSymbol implmeth = absmeth.implementation(impl, types, true);
                         if (implmeth == null || implmeth == absmeth) {
                             //look for default implementations
@@ -2113,6 +2098,7 @@
                         }
                         if (implmeth == null || implmeth == absmeth) {
                             undef = absmeth;
+                            break;
                         }
                     }
                 }
@@ -2336,10 +2322,10 @@
             for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
                 ClassSymbol lc = (ClassSymbol)l.head.tsym;
                 if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) {
-                    for (Scope.Entry e=lc.members().elems; e != null; e=e.sibling) {
-                        if (e.sym.kind == MTH &&
-                            (e.sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) {
-                            MethodSymbol absmeth = (MethodSymbol)e.sym;
+                    for (Symbol sym : lc.members().getSymbols(NON_RECURSIVE)) {
+                        if (sym.kind == MTH &&
+                            (sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) {
+                            MethodSymbol absmeth = (MethodSymbol)sym;
                             MethodSymbol implmeth = absmeth.implementation(origin, types, false);
                             if (implmeth != null && implmeth != absmeth &&
                                 (implmeth.owner.flags() & INTERFACE) ==
@@ -2382,15 +2368,15 @@
 
     void checkConflicts(DiagnosticPosition pos, Symbol sym, TypeSymbol c) {
         for (Type ct = c.type; ct != Type.noType ; ct = types.supertype(ct)) {
-            for (Scope.Entry e = ct.tsym.members().lookup(sym.name); e.scope == ct.tsym.members(); e = e.next()) {
+            for (Symbol sym2 : ct.tsym.members().getSymbolsByName(sym.name, NON_RECURSIVE)) {
                 // VM allows methods and variables with differing types
-                if (sym.kind == e.sym.kind &&
-                    types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) &&
-                    sym != e.sym &&
-                    (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) &&
-                    (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 &&
-                    (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) {
-                    syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym);
+                if (sym.kind == sym2.kind &&
+                    types.isSameType(types.erasure(sym.type), types.erasure(sym2.type)) &&
+                    sym != sym2 &&
+                    (sym.flags() & Flags.SYNTHETIC) != (sym2.flags() & Flags.SYNTHETIC) &&
+                    (sym.flags() & IPROXY) == 0 && (sym2.flags() & IPROXY) == 0 &&
+                    (sym.flags() & BRIDGE) == 0 && (sym2.flags() & BRIDGE) == 0) {
+                    syntheticError(pos, (sym2.flags() & SYNTHETIC) == 0 ? sym2 : sym);
                     return;
                 }
             }
@@ -2411,7 +2397,7 @@
 
         List<MethodSymbol> potentiallyAmbiguousList = List.nil();
         boolean overridesAny = false;
-        for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
+        for (Symbol m1 : types.membersClosure(site, false).getSymbolsByName(sym.name, cf)) {
             if (!sym.overrides(m1, site.tsym, types, false)) {
                 if (m1 == sym) {
                     continue;
@@ -2429,7 +2415,7 @@
             }
 
             //...check each method m2 that is a member of 'site'
-            for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
+            for (Symbol m2 : types.membersClosure(site, false).getSymbolsByName(sym.name, cf)) {
                 if (m2 == m1) continue;
                 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
                 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
@@ -2466,7 +2452,7 @@
     void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
         ClashFilter cf = new ClashFilter(site);
         //for each method m1 that is a member of 'site'...
-        for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
+        for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) {
             //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
             //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
             if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
@@ -2508,7 +2494,7 @@
 
     void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
         DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
-        for (Symbol m : types.membersClosure(site, false).getElements(dcf)) {
+        for (Symbol m : types.membersClosure(site, false).getSymbols(dcf)) {
             Assert.check(m.kind == MTH);
             List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
             if (prov.size() > 1) {
@@ -2772,11 +2758,11 @@
     void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) {
         for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) {
             Scope s = sup.tsym.members();
-            for (Scope.Entry e = s.lookup(m.name); e.scope != null; e = e.next()) {
-                if (e.sym.kind == MTH &&
-                    (e.sym.flags() & (PUBLIC | PROTECTED)) != 0 &&
-                    types.overrideEquivalent(m.type, e.sym.type))
-                    log.error(pos, "intf.annotation.member.clash", e.sym, sup);
+            for (Symbol sym : s.getSymbolsByName(m.name)) {
+                if (sym.kind == MTH &&
+                    (sym.flags() & (PUBLIC | PROTECTED)) != 0 &&
+                    types.overrideEquivalent(m.type, sym.type))
+                    log.error(pos, "intf.annotation.member.clash", sym, sup);
             }
         }
     }
@@ -2856,9 +2842,9 @@
     }
 
     private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
-        Scope.Entry e = container.members().lookup(names.value);
-        if (e.scope != null && e.sym.kind == MTH) {
-            MethodSymbol m = (MethodSymbol) e.sym;
+        Symbol sym = container.members().findFirst(names.value);
+        if (sym != null && sym.kind == MTH) {
+            MethodSymbol m = (MethodSymbol) sym;
             Type ret = m.getReturnType();
             if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) {
                 log.error(pos, "invalid.repeatable.annotation.value.return",
@@ -3003,7 +2989,7 @@
     private void validateDefault(Symbol container, DiagnosticPosition pos) {
         // validate that all other elements of containing type has defaults
         Scope scope = container.members();
-        for(Symbol elm : scope.getElements()) {
+        for(Symbol elm : scope.getSymbols()) {
             if (elm.name != names.value &&
                 elm.kind == Kinds.MTH &&
                 ((MethodSymbol)elm).defaultValue == null) {
@@ -3025,8 +3011,8 @@
             if (sup == owner.type)
                 continue; // skip "this"
             Scope scope = sup.tsym.members();
-            for (Scope.Entry e = scope.lookup(m.name); e.scope != null; e = e.next()) {
-                if (!e.sym.isStatic() && m.overrides(e.sym, owner, types, true))
+            for (Symbol sym : scope.getSymbolsByName(m.name)) {
+                if (!sym.isStatic() && m.overrides(sym, owner, types, true))
                     return true;
             }
         }
@@ -3160,12 +3146,10 @@
         boolean isValid = true;
         // collect an inventory of the annotation elements
         Set<MethodSymbol> members = new LinkedHashSet<>();
-        for (Scope.Entry e = a.annotationType.type.tsym.members().elems;
-                e != null;
-                e = e.sibling)
-            if (e.sym.kind == MTH && e.sym.name != names.clinit &&
-                    (e.sym.flags() & SYNTHETIC) == 0)
-                members.add((MethodSymbol) e.sym);
+        for (Symbol sym : a.annotationType.type.tsym.members().getSymbols(NON_RECURSIVE))
+            if (sym.kind == MTH && sym.name != names.clinit &&
+                    (sym.flags() & SYNTHETIC) == 0)
+                members.add((MethodSymbol) sym);
 
         // remove the ones that are assigned values
         for (JCTree arg : a.args) {
@@ -3293,8 +3277,7 @@
         }
         try {
             tsym.flags_field |= LOCKED;
-            for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
-                Symbol s = e.sym;
+            for (Symbol s : tsym.members().getSymbols(NON_RECURSIVE)) {
                 if (s.kind != Kinds.MTH)
                     continue;
                 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType());
@@ -3436,23 +3419,23 @@
         if (sym.type.isErroneous())
             return true;
         if (sym.owner.name == names.any) return false;
-        for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
-            if (sym != e.sym &&
-                    (e.sym.flags() & CLASH) == 0 &&
-                    sym.kind == e.sym.kind &&
+        for (Symbol byName : s.getSymbolsByName(sym.name, NON_RECURSIVE)) {
+            if (sym != byName &&
+                    (byName.flags() & CLASH) == 0 &&
+                    sym.kind == byName.kind &&
                     sym.name != names.error &&
                     (sym.kind != MTH ||
-                     types.hasSameArgs(sym.type, e.sym.type) ||
-                     types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
-                if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) {
-                    varargsDuplicateError(pos, sym, e.sym);
+                     types.hasSameArgs(sym.type, byName.type) ||
+                     types.hasSameArgs(types.erasure(sym.type), types.erasure(byName.type)))) {
+                if ((sym.flags() & VARARGS) != (byName.flags() & VARARGS)) {
+                    varargsDuplicateError(pos, sym, byName);
                     return true;
-                } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, e.sym.type, false)) {
-                    duplicateErasureError(pos, sym, e.sym);
+                } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, false)) {
+                    duplicateErasureError(pos, sym, byName);
                     sym.flags_field |= CLASH;
                     return true;
                 } else {
-                    duplicateError(pos, e.sym);
+                    duplicateError(pos, byName);
                     return false;
                 }
             }
@@ -3471,47 +3454,50 @@
     /** Check that single-type import is not already imported or top-level defined,
      *  but make an exception for two single-type imports which denote the same type.
      *  @param pos           Position for error reporting.
+     *  @param toplevel      The file in which in the check is performed.
      *  @param sym           The symbol.
-     *  @param s             The scope
      */
-    boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s) {
-        return checkUniqueImport(pos, sym, s, false);
+    boolean checkUniqueImport(DiagnosticPosition pos, JCCompilationUnit toplevel, Symbol sym) {
+        return checkUniqueImport(pos, toplevel, sym, false);
     }
 
     /** Check that static single-type import is not already imported or top-level defined,
      *  but make an exception for two single-type imports which denote the same type.
      *  @param pos           Position for error reporting.
+     *  @param toplevel      The file in which in the check is performed.
      *  @param sym           The symbol.
-     *  @param s             The scope
      */
-    boolean checkUniqueStaticImport(DiagnosticPosition pos, Symbol sym, Scope s) {
-        return checkUniqueImport(pos, sym, s, true);
+    boolean checkUniqueStaticImport(DiagnosticPosition pos, JCCompilationUnit toplevel, Symbol sym) {
+        return checkUniqueImport(pos, toplevel, sym, true);
     }
 
     /** Check that single-type import is not already imported or top-level defined,
      *  but make an exception for two single-type imports which denote the same type.
      *  @param pos           Position for error reporting.
+     *  @param toplevel      The file in which in the check is performed.
      *  @param sym           The symbol.
-     *  @param s             The scope.
      *  @param staticImport  Whether or not this was a static import
      */
-    private boolean checkUniqueImport(DiagnosticPosition pos, Symbol sym, Scope s, boolean staticImport) {
-        for (Scope.Entry e = s.lookup(sym.name); e.scope != null; e = e.next()) {
+    private boolean checkUniqueImport(DiagnosticPosition pos, JCCompilationUnit toplevel, Symbol sym, boolean staticImport) {
+        NamedImportScope namedImportScope = toplevel.namedImportScope;
+        WriteableScope topLevelScope = toplevel.toplevelScope;
+
+        for (Symbol byName : namedImportScope.getSymbolsByName(sym.name)) {
             // is encountered class entered via a class declaration?
-            boolean isClassDecl = e.scope == s;
-            if ((isClassDecl || sym != e.sym) &&
-                sym.kind == e.sym.kind &&
+            boolean isClassDecl = namedImportScope.getOrigin(byName) == topLevelScope;
+            if ((isClassDecl || sym != byName) &&
+                sym.kind == byName.kind &&
                 sym.name != names.error &&
-                (!staticImport || !e.isStaticallyImported())) {
-                if (!e.sym.type.isErroneous()) {
+                (!staticImport || !namedImportScope.isStaticallyImported(byName))) {
+                if (!byName.type.isErroneous()) {
                     if (!isClassDecl) {
                         if (staticImport)
-                            log.error(pos, "already.defined.static.single.import", e.sym);
+                            log.error(pos, "already.defined.static.single.import", byName);
                         else
-                        log.error(pos, "already.defined.single.import", e.sym);
+                        log.error(pos, "already.defined.single.import", byName);
                     }
-                    else if (sym != e.sym)
-                        log.error(pos, "already.defined.this.unit", e.sym);
+                    else if (sym != byName)
+                        log.error(pos, "already.defined.this.unit", byName);
                 }
                 return false;
             }
@@ -3610,4 +3596,68 @@
             }
         }
     }
+
+    public void checkImportsResolvable(final JCCompilationUnit toplevel) {
+        for (final JCImport imp : toplevel.getImports()) {
+            if (!imp.staticImport || !imp.qualid.hasTag(SELECT))
+                continue;
+            final JCFieldAccess select = (JCFieldAccess) imp.qualid;
+            final Symbol origin;
+            if (select.name == names.asterisk || (origin = TreeInfo.symbol(select.selected)) == null || origin.kind != TYP)
+                continue;
+
+            JavaFileObject prev = log.useSource(toplevel.sourcefile);
+            try {
+                TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected);
+                if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) {
+                    log.error(imp.pos(), "cant.resolve.location",
+                              KindName.STATIC,
+                              select.name, List.<Type>nil(), List.<Type>nil(),
+                              Kinds.typeKindName(TreeInfo.symbol(select.selected).type),
+                              TreeInfo.symbol(select.selected).type);
+                }
+            } finally {
+                log.useSource(prev);
+            }
+        }
+    }
+
+    private boolean checkTypeContainsImportableElement(TypeSymbol tsym, TypeSymbol origin, PackageSymbol packge, Name name, Set<Symbol> processed) {
+        if (tsym == null || !processed.add(tsym))
+            return false;
+
+            // also search through inherited names
+        if (checkTypeContainsImportableElement(types.supertype(tsym.type).tsym, origin, packge, name, processed))
+            return true;
+
+        for (Type t : types.interfaces(tsym.type))
+            if (checkTypeContainsImportableElement(t.tsym, origin, packge, name, processed))
+                return true;
+
+        for (Symbol sym : tsym.members().getSymbolsByName(name)) {
+            if (sym.isStatic() &&
+                staticImportAccessible(sym, packge) &&
+                sym.isMemberOf(origin, types)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    // is the sym accessible everywhere in packge?
+    public boolean staticImportAccessible(Symbol sym, PackageSymbol packge) {
+        int flags = (int)(sym.flags() & AccessFlags);
+        switch (flags) {
+        default:
+        case PUBLIC:
+            return true;
+        case PRIVATE:
+            return false;
+        case 0:
+        case PROTECTED:
+            return sym.packge() == packge;
+        }
+    }
+
 }