aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcushon <cushon@google.com>2016-12-14 18:43:55 -0800
committerLiam Miller-Cushon <cushon@google.com>2016-12-14 23:04:40 -0800
commit2f66fb86c5de3e13b58b1a521ffc307c8cef1f50 (patch)
tree9d24995f7969bb1f84b72650bd054f26fd5aaf3e
parent17f7dd1db1cc0177e7a36cc82eada865293c1855 (diff)
downloadturbine-2f66fb86c5de3e13b58b1a521ffc307c8cef1f50.tar.gz
Check visibility of static on-demand type imports
Move initial modifier handling earlier in binding, and use it to filter private class and fields from on-demand imports. MOE_MIGRATED_REVID=142092576
-rw-r--r--java/com/google/turbine/binder/Binder.java39
-rw-r--r--java/com/google/turbine/binder/ConstEvaluator.java10
-rw-r--r--java/com/google/turbine/binder/HierarchyBinder.java28
-rw-r--r--java/com/google/turbine/binder/Resolve.java24
-rw-r--r--java/com/google/turbine/binder/TypeBinder.java3
-rw-r--r--java/com/google/turbine/binder/bound/BoundClass.java3
-rw-r--r--java/com/google/turbine/binder/bound/HeaderBoundClass.java3
-rw-r--r--java/com/google/turbine/binder/bound/PackageSourceBoundClass.java5
-rw-r--r--java/com/google/turbine/binder/bound/SourceBoundClass.java13
-rw-r--r--javatests/com/google/turbine/lower/LowerIntegrationTest.java2
-rw-r--r--javatests/com/google/turbine/lower/testdata/B33513475b.test19
-rw-r--r--javatests/com/google/turbine/lower/testdata/B33513475c.test16
12 files changed, 124 insertions, 41 deletions
diff --git a/java/com/google/turbine/binder/Binder.java b/java/com/google/turbine/binder/Binder.java
index 9262a1f..bdc6c23 100644
--- a/java/com/google/turbine/binder/Binder.java
+++ b/java/com/google/turbine/binder/Binder.java
@@ -52,6 +52,7 @@ import com.google.turbine.binder.sym.FieldSymbol;
import com.google.turbine.model.Const;
import com.google.turbine.model.TurbineFlag;
import com.google.turbine.model.TurbineTyKind;
+import com.google.turbine.model.TurbineVisibility;
import com.google.turbine.tree.Tree;
import com.google.turbine.tree.Tree.CompUnit;
import com.google.turbine.tree.Tree.PkgDecl;
@@ -141,9 +142,11 @@ public class Binder {
for (Tree.TyDecl decl : decls) {
ClassSymbol sym = new ClassSymbol(packagename + decl.name());
ImmutableMap<String, ClassSymbol> children =
- bindSourceBoundClassMembers(envbuilder, sym, decl.members(), toplevels, unit);
+ bindSourceBoundClassMembers(
+ envbuilder, sym, decl.members(), toplevels, unit, decl.tykind());
if (envbuilder.putIfAbsent(
- sym, new SourceBoundClass(decl, null, decl.tykind(), children))) {
+ sym,
+ new SourceBoundClass(decl, null, decl.tykind(), children, access(null, decl.mods())))) {
toplevels.put(unit, sym);
}
tliBuilder.insert(sym);
@@ -152,6 +155,25 @@ public class Binder {
return envbuilder.build();
}
+ private static int access(TurbineTyKind enclosing, ImmutableSet<TurbineModifier> mods) {
+ int access = 0;
+ for (TurbineModifier m : mods) {
+ access |= m.flag();
+ }
+ // types declared in interfaces and annotations are implicitly public (JLS 9.5)
+ if (enclosing != null) {
+ switch (enclosing) {
+ case INTERFACE:
+ case ANNOTATION:
+ access = TurbineVisibility.PUBLIC.setAccess(access);
+ break;
+ default:
+ break;
+ }
+ }
+ return access;
+ }
+
/** Fakes up the synthetic type declaration for a package-info.java file. */
private static TyDecl packageInfoTree(PkgDecl pkgDecl) {
return new TyDecl(
@@ -172,7 +194,8 @@ public class Binder {
ClassSymbol owner,
ImmutableList<Tree> members,
Multimap<CompUnit, ClassSymbol> toplevels,
- CompUnit unit) {
+ CompUnit unit,
+ TurbineTyKind enclosing) {
ImmutableMap.Builder<String, ClassSymbol> result = ImmutableMap.builder();
for (Tree member : members) {
if (member.kind() == Tree.Kind.TY_DECL) {
@@ -181,8 +204,11 @@ public class Binder {
toplevels.put(unit, sym);
result.put(decl.name(), sym);
ImmutableMap<String, ClassSymbol> children =
- bindSourceBoundClassMembers(env, sym, decl.members(), toplevels, unit);
- env.putIfAbsent(sym, new SourceBoundClass(decl, owner, decl.tykind(), children));
+ bindSourceBoundClassMembers(env, sym, decl.members(), toplevels, unit, decl.tykind());
+ env.putIfAbsent(
+ sym,
+ new SourceBoundClass(
+ decl, owner, decl.tykind(), children, access(enclosing, decl.mods())));
}
}
return result.build();
@@ -204,7 +230,8 @@ public class Binder {
unit.pkg().isPresent() ? unit.pkg().get().name() : ImmutableList.of();
Scope packageScope = tli.lookupPackage(packagename);
CanonicalSymbolResolver importResolver =
- new CanonicalResolver(CompoundEnv.<ClassSymbol, BoundClass>of(ienv).append(classPathEnv));
+ new CanonicalResolver(
+ packagename, CompoundEnv.<ClassSymbol, BoundClass>of(ienv).append(classPathEnv));
Scope importScope = ImportIndex.create(importResolver, tli, unit.imports());
Scope wildImportScope = WildImportIndex.create(importResolver, tli, unit.imports());
MemberImportIndex memberImports = new MemberImportIndex(importResolver, tli, unit.imports());
diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java
index b744339..7156a87 100644
--- a/java/com/google/turbine/binder/ConstEvaluator.java
+++ b/java/com/google/turbine/binder/ConstEvaluator.java
@@ -235,9 +235,15 @@ public strictfp class ConstEvaluator {
Iterator<ClassSymbol> it = base.memberImports().onDemandImports();
while (it.hasNext()) {
field = Resolve.resolveField(env, owner, it.next(), simpleName);
- if (field != null) {
- return field;
+ if (field == null) {
+ continue;
}
+ // resolve handles visibility of inherited members; on-demand imports of private members are
+ // a special case
+ if ((field.access() & TurbineFlag.ACC_PRIVATE) == TurbineFlag.ACC_PRIVATE) {
+ continue;
+ }
+ return field;
}
return null;
}
diff --git a/java/com/google/turbine/binder/HierarchyBinder.java b/java/com/google/turbine/binder/HierarchyBinder.java
index 8416202..cc96eaf 100644
--- a/java/com/google/turbine/binder/HierarchyBinder.java
+++ b/java/com/google/turbine/binder/HierarchyBinder.java
@@ -31,9 +31,7 @@ import com.google.turbine.diag.TurbineError;
import com.google.turbine.diag.TurbineError.ErrorKind;
import com.google.turbine.model.TurbineFlag;
import com.google.turbine.model.TurbineTyKind;
-import com.google.turbine.model.TurbineVisibility;
import com.google.turbine.tree.Tree;
-import com.google.turbine.tree.TurbineModifier;
import java.util.ArrayDeque;
/** Type hierarchy binding. */
@@ -62,11 +60,7 @@ public class HierarchyBinder {
private SourceHeaderBoundClass bind() {
Tree.TyDecl decl = base.decl();
-
- int access = 0;
- for (TurbineModifier m : decl.mods()) {
- access |= m.flag();
- }
+ int access = base.access();
switch (decl.tykind()) {
case CLASS:
access |= TurbineFlag.ACC_SUPER;
@@ -84,11 +78,6 @@ public class HierarchyBinder {
throw new AssertionError(decl.tykind());
}
- // types declared in interfaces annotations are implicitly public (JLS 9.5)
- if (enclosedByInterface(base)) {
- access = TurbineVisibility.PUBLIC.setAccess(access);
- }
-
if ((access & TurbineFlag.ACC_STATIC) == 0 && implicitStatic(base)) {
access |= TurbineFlag.ACC_STATIC;
}
@@ -170,21 +159,6 @@ public class HierarchyBinder {
}
}
- /** Returns true if the given type is declared in an interface. */
- private boolean enclosedByInterface(BoundClass c) {
- if (c.owner() != null) {
- HeaderBoundClass info = env.get(c.owner());
- switch (info.kind()) {
- case INTERFACE:
- case ANNOTATION:
- return true;
- default:
- break;
- }
- }
- return false;
- }
-
/**
* Resolves the {@link ClassSymbol} for the given {@link Tree.ClassTy}, with handling for
* non-canonical qualified type names.
diff --git a/java/com/google/turbine/binder/Resolve.java b/java/com/google/turbine/binder/Resolve.java
index 7b9e490..ad033cd 100644
--- a/java/com/google/turbine/binder/Resolve.java
+++ b/java/com/google/turbine/binder/Resolve.java
@@ -16,6 +16,8 @@
package com.google.turbine.binder;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
import com.google.turbine.binder.bound.BoundClass;
import com.google.turbine.binder.bound.HeaderBoundClass;
import com.google.turbine.binder.bound.TypeBoundClass;
@@ -66,9 +68,12 @@ public class Resolve {
}
static class CanonicalResolver implements CanonicalSymbolResolver {
+ private final String packagename;
private final CompoundEnv<ClassSymbol, BoundClass> env;
- public CanonicalResolver(CompoundEnv<ClassSymbol, BoundClass> env) {
+ public CanonicalResolver(
+ ImmutableList<String> packagename, CompoundEnv<ClassSymbol, BoundClass> env) {
+ this.packagename = Joiner.on('/').join(packagename);
this.env = env;
}
@@ -94,8 +99,25 @@ public class Resolve {
if (sym == null) {
return null;
}
+ if (!visible(sym, TurbineVisibility.fromAccess(env.get(sym).access()))) {
+ return null;
+ }
return sym;
}
+
+ boolean visible(ClassSymbol sym, TurbineVisibility visibility) {
+ switch (visibility) {
+ case PUBLIC:
+ return true;
+ case PROTECTED:
+ case PACKAGE:
+ return Objects.equals(packageName(sym), packagename);
+ case PRIVATE:
+ return false;
+ default:
+ throw new AssertionError(visibility);
+ }
+ }
}
/**
diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java
index b770109..c100fd1 100644
--- a/java/com/google/turbine/binder/TypeBinder.java
+++ b/java/com/google/turbine/binder/TypeBinder.java
@@ -651,6 +651,9 @@ public class TypeBinder {
for (; idx < flat.size(); idx++) {
Tree.ClassTy curr = flat.get(idx);
sym = Resolve.resolve(env, owner, sym, curr.name());
+ if (sym == null) {
+ throw error(curr.position(), ErrorKind.CANNOT_RESOLVE, curr.name());
+ }
annotations = bindAnnotations(scope, curr.annos());
classes.add(
new Type.ClassTy.SimpleClassTy(sym, bindTyArgs(scope, curr.tyargs()), annotations));
diff --git a/java/com/google/turbine/binder/bound/BoundClass.java b/java/com/google/turbine/binder/bound/BoundClass.java
index 29ef196..ad26af7 100644
--- a/java/com/google/turbine/binder/bound/BoundClass.java
+++ b/java/com/google/turbine/binder/bound/BoundClass.java
@@ -35,6 +35,9 @@ public interface BoundClass {
@Nullable
ClassSymbol owner();
+ /** Class access bits (see JVMS table 4.1). */
+ int access();
+
/** Member type declarations, by simple name. */
ImmutableMap<String, ClassSymbol> children();
}
diff --git a/java/com/google/turbine/binder/bound/HeaderBoundClass.java b/java/com/google/turbine/binder/bound/HeaderBoundClass.java
index bc8edb3..14807bb 100644
--- a/java/com/google/turbine/binder/bound/HeaderBoundClass.java
+++ b/java/com/google/turbine/binder/bound/HeaderBoundClass.java
@@ -29,9 +29,6 @@ public interface HeaderBoundClass extends BoundClass {
/** The interfaces of the declaration. */
ImmutableList<ClassSymbol> interfaces();
- /** Class access bits (see JVMS table 4.1). */
- int access();
-
/** Declared type parameters. */
public ImmutableMap<String, TyVarSymbol> typeParameters();
}
diff --git a/java/com/google/turbine/binder/bound/PackageSourceBoundClass.java b/java/com/google/turbine/binder/bound/PackageSourceBoundClass.java
index 6b708f9..946bd90 100644
--- a/java/com/google/turbine/binder/bound/PackageSourceBoundClass.java
+++ b/java/com/google/turbine/binder/bound/PackageSourceBoundClass.java
@@ -57,6 +57,11 @@ public class PackageSourceBoundClass implements BoundClass {
}
@Override
+ public int access() {
+ return base.access();
+ }
+
+ @Override
public ImmutableMap<String, ClassSymbol> children() {
return base.children();
}
diff --git a/java/com/google/turbine/binder/bound/SourceBoundClass.java b/java/com/google/turbine/binder/bound/SourceBoundClass.java
index c9afc3b..3373cce 100644
--- a/java/com/google/turbine/binder/bound/SourceBoundClass.java
+++ b/java/com/google/turbine/binder/bound/SourceBoundClass.java
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.turbine.binder.sym.ClassSymbol;
import com.google.turbine.model.TurbineTyKind;
import com.google.turbine.tree.Tree;
+import com.google.turbine.tree.Tree.TyDecl;
/** A {@link BoundClass} that corresponds to a source file being compiled. */
public class SourceBoundClass implements BoundClass {
@@ -27,16 +28,19 @@ public class SourceBoundClass implements BoundClass {
private final ClassSymbol owner;
private final TurbineTyKind kind;
private final ImmutableMap<String, ClassSymbol> children;
+ private final int access;
public SourceBoundClass(
- Tree.TyDecl decl,
+ TyDecl decl,
ClassSymbol owner,
TurbineTyKind kind,
- ImmutableMap<String, ClassSymbol> children) {
+ ImmutableMap<String, ClassSymbol> children,
+ int access) {
this.decl = decl;
this.owner = owner;
this.kind = kind;
this.children = children;
+ this.access = access;
}
public Tree.TyDecl decl() {
@@ -54,6 +58,11 @@ public class SourceBoundClass implements BoundClass {
}
@Override
+ public int access() {
+ return access;
+ }
+
+ @Override
public ImmutableMap<String, ClassSymbol> children() {
return children;
}
diff --git a/javatests/com/google/turbine/lower/LowerIntegrationTest.java b/javatests/com/google/turbine/lower/LowerIntegrationTest.java
index f3268d4..7b80d90 100644
--- a/javatests/com/google/turbine/lower/LowerIntegrationTest.java
+++ b/javatests/com/google/turbine/lower/LowerIntegrationTest.java
@@ -287,6 +287,8 @@ public class LowerIntegrationTest {
"typaram_lookup.test",
"typaram_lookup_enclosing.test",
"B33513475.test",
+ "B33513475b.test",
+ "B33513475c.test",
};
List<Object[]> tests =
ImmutableList.copyOf(testCases).stream().map(x -> new Object[] {x}).collect(toList());
diff --git a/javatests/com/google/turbine/lower/testdata/B33513475b.test b/javatests/com/google/turbine/lower/testdata/B33513475b.test
new file mode 100644
index 0000000..f92a40b
--- /dev/null
+++ b/javatests/com/google/turbine/lower/testdata/B33513475b.test
@@ -0,0 +1,19 @@
+=== p/A.java ===
+package p;
+import static p.A.I.*;
+import static p.B.*;
+class A {
+ static class I {
+ private static class Inner {
+ }
+ }
+ Inner.InnerMost i;
+}
+
+=== p/B.java ===
+package p;
+public class B {
+ public static class Inner {
+ protected static class InnerMost {}
+ }
+}
diff --git a/javatests/com/google/turbine/lower/testdata/B33513475c.test b/javatests/com/google/turbine/lower/testdata/B33513475c.test
new file mode 100644
index 0000000..abbf346
--- /dev/null
+++ b/javatests/com/google/turbine/lower/testdata/B33513475c.test
@@ -0,0 +1,16 @@
+=== p/A.java ===
+package p;
+import static p.A.I.*;
+import static p.B.*;
+class A {
+ static class I {
+ private static final int N = 1;
+ }
+ static final int M = N;
+}
+
+=== p/B.java ===
+package p;
+public class B {
+ public static final int N = 2;
+}