8154705: invalid use of ALL-MODULE-PATH causes crash

Introducing Modules.initModules as a clear point where the module graphs is initialized in javac

Reviewed-by: jjg, ksrini
This commit is contained in:
Kumar Srinivasan 2016-07-20 12:49:32 -07:00
parent fca2c3ce3f
commit 281438728d
11 changed files with 135 additions and 87 deletions

View File

@ -38,6 +38,7 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -148,7 +149,7 @@ public class Modules extends JCTree.Visitor {
private final String addModsOpt;
private final String limitModsOpt;
private Set<ModuleSymbol> rootModules = Collections.emptySet();
private Set<ModuleSymbol> rootModules = null;
public static Modules instance(Context context) {
Modules instance = context.get(Modules.class);
@ -194,7 +195,31 @@ public class Modules extends JCTree.Visitor {
System.err.println(msg);
}
boolean inInitModules;
public void initModules(List<JCCompilationUnit> trees, Collection<String> extraAddMods, Collection<String> extraLimitMods) {
Assert.check(!inInitModules);
try {
inInitModules = true;
Assert.checkNull(rootModules);
enter(trees, modules -> {
Assert.checkNull(rootModules);
Assert.checkNull(allModules);
this.rootModules = modules;
setupAllModules(extraAddMods, extraLimitMods); //initialize the module graph
Assert.checkNonNull(allModules);
inInitModules = false;
}, null);
} finally {
inInitModules = false;
}
}
public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) {
Assert.check(rootModules != null || inInitModules || !allowModules);
return enter(trees, modules -> {}, c);
}
private boolean enter(List<JCCompilationUnit> trees, Consumer<Set<ModuleSymbol>> init, ClassSymbol c) {
if (!allowModules) {
for (JCCompilationUnit tree: trees) {
tree.modle = syms.noModule;
@ -212,10 +237,7 @@ public class Modules extends JCTree.Visitor {
setCompilationUnitModules(trees, roots);
if (!roots.isEmpty() && this.rootModules.isEmpty()) {
this.rootModules = roots;
allModules(); //ensure errors reported
}
init.accept(roots);
for (ModuleSymbol msym: roots) {
msym.complete();
@ -395,6 +417,7 @@ public class Modules extends JCTree.Visitor {
defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
} else {
Assert.check(rootModules.isEmpty());
rootModules.add(defaultModule);
}
if (defaultModule != syms.unnamedModule) {
@ -462,7 +485,7 @@ public class Modules extends JCTree.Visitor {
msym.requires = List.nil();
msym.uses = List.nil();
} else if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) {
completeAutomaticModule(msym);
setupAutomaticModule(msym);
} else {
msym.module_info.complete();
}
@ -485,7 +508,7 @@ public class Modules extends JCTree.Visitor {
}
};
private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
private void setupAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
try {
ListBuffer<Directive> directives = new ListBuffer<>();
ListBuffer<ExportsDirective> exports = new ListBuffer<>();
@ -501,28 +524,9 @@ public class Modules extends JCTree.Visitor {
}
}
ListBuffer<RequiresDirective> requires = new ListBuffer<>();
//ensure all modules are found:
moduleFinder.findAllModules();
for (ModuleSymbol ms : allModules()) {
if (ms == syms.unnamedModule || ms == msym)
continue;
Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ?
EnumSet.of(RequiresFlag.PUBLIC) : EnumSet.noneOf(RequiresFlag.class);
RequiresDirective d = new RequiresDirective(ms, flags);
directives.add(d);
requires.add(d);
}
RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
directives.add(requiresUnnamed);
requires.add(requiresUnnamed);
msym.exports = exports.toList();
msym.provides = List.nil();
msym.requires = requires.toList();
msym.requires = List.nil();
msym.uses = List.nil();
msym.directives = directives.toList();
msym.flags_field |= Flags.ACYCLIC;
@ -531,6 +535,31 @@ public class Modules extends JCTree.Visitor {
}
}
private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
ListBuffer<Directive> directives = new ListBuffer<>();
directives.addAll(msym.directives);
ListBuffer<RequiresDirective> requires = new ListBuffer<>();
for (ModuleSymbol ms : allModules()) {
if (ms == syms.unnamedModule || ms == msym)
continue;
Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ?
EnumSet.of(RequiresFlag.PUBLIC) : EnumSet.noneOf(RequiresFlag.class);
RequiresDirective d = new RequiresDirective(ms, flags);
directives.add(d);
requires.add(d);
}
RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
directives.add(requiresUnnamed);
requires.add(requiresUnnamed);
msym.requires = requires.toList();
msym.directives = directives.toList();
}
private Completer getSourceCompleter(JCCompilationUnit tree) {
return new Completer() {
@Override
@ -541,8 +570,8 @@ public class Modules extends JCTree.Visitor {
JavaFileObject prev = log.useSource(tree.sourcefile);
try {
tree.defs.head.accept(v);
completeModule(msym);
checkCyclicDependencies((JCModuleDecl) tree.defs.head);
completeModule(msym);
} finally {
log.useSource(prev);
msym.flags_field &= ~UNATTRIBUTED;
@ -660,6 +689,9 @@ public class Modules extends JCTree.Visitor {
public Completer getUsesProvidesCompleter() {
return sym -> {
ModuleSymbol msym = (ModuleSymbol) sym;
msym.complete();
Env<AttrContext> env = typeEnvs.get(msym);
UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
@ -823,19 +855,29 @@ public class Modules extends JCTree.Visitor {
}
}
private Set<ModuleSymbol> allModulesCache;
private Set<ModuleSymbol> allModules;
private Set<ModuleSymbol> allModules() {
if (allModulesCache != null)
return allModulesCache;
public Set<ModuleSymbol> allModules() {
Assert.checkNonNull(allModules);
return allModules;
}
private void setupAllModules(Collection<String> extraAddMods, Collection<String> extraLimitMods) {
Assert.checkNonNull(rootModules);
Assert.checkNull(allModules);
Set<ModuleSymbol> observable;
if (limitModsOpt == null) {
if (limitModsOpt == null && extraLimitMods.isEmpty()) {
observable = null;
} else {
Set<ModuleSymbol> limitMods = new HashSet<>();
for (String limit : limitModsOpt.split(",")) {
if (limitModsOpt != null) {
for (String limit : limitModsOpt.split(",")) {
limitMods.add(syms.enterModule(names.fromString(limit)));
}
}
for (String limit : extraLimitMods) {
limitMods.add(syms.enterModule(names.fromString(limit)));
}
observable = computeTransitiveClosure(limitMods, null);
@ -870,8 +912,15 @@ public class Modules extends JCTree.Visitor {
enabledRoot.addAll(rootModules);
if (addModsOpt != null) {
for (String added : addModsOpt.split(",")) {
if (addModsOpt != null || !extraAddMods.isEmpty()) {
Set<String> fullAddMods = new HashSet<>();
fullAddMods.addAll(extraAddMods);
if (addModsOpt != null) {
fullAddMods.addAll(Arrays.asList(addModsOpt.split(",")));
}
for (String added : fullAddMods) {
Stream<ModuleSymbol> modules;
switch (added) {
case ALL_SYSTEM:
@ -900,20 +949,7 @@ public class Modules extends JCTree.Visitor {
result.add(syms.unnamedModule);
if (!rootModules.isEmpty())
allModulesCache = result;
return result;
}
public void enableAllModules() {
allModulesCache = new HashSet<>();
moduleFinder.findAllModules();
for (ModuleSymbol msym : syms.getAllModules()) {
allModulesCache.add(msym);
}
allModules = result;
}
private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
@ -975,6 +1011,15 @@ public class Modules extends JCTree.Visitor {
private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>();
private void completeModule(ModuleSymbol msym) {
if (inInitModules) {
msym.completer = sym -> completeModule(msym);
return ;
}
if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) {
completeAutomaticModule(msym);
}
Assert.checkNonNull(msym.requires);
initAddReads();
@ -1226,9 +1271,9 @@ public class Modules extends JCTree.Visitor {
queue = queue.tail;
if (!nonSyntheticDeps.add(current))
continue;
current.complete();
if ((current.flags() & Flags.ACYCLIC) != 0)
continue;
current.complete();
Assert.checkNonNull(current.requires, () -> current.toString());
for (RequiresDirective dep : current.requires) {
if (!dep.flags.contains(RequiresFlag.EXTRA))
@ -1264,5 +1309,7 @@ public class Modules extends JCTree.Visitor {
}
public void newRound() {
rootModules = null;
allModules = null;
}
}

View File

@ -27,6 +27,7 @@ package com.sun.tools.javac.main;
import java.io.*;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -1009,15 +1010,10 @@ public class JavaCompiler {
}
public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
List<JCCompilationUnit> result = initModules(roots, null);
modules.initModules(roots, Collections.emptySet(), Collections.emptySet());
if (roots.isEmpty()) {
enterDone = true;
}
return result;
}
List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots, ClassSymbol c) {
modules.enter(roots, c);
return roots;
}

View File

@ -28,6 +28,7 @@ package com.sun.tools.javadoc.main;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -44,6 +45,7 @@ import javax.tools.StandardLocation;
import com.sun.tools.javac.code.ClassFinder;
import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@ -52,6 +54,7 @@ import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
/**
@ -183,9 +186,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
// Parse file objects provide via the DocumentationTool API
parse(fileObjects, classTrees, true);
modules.enter(classTrees.toList(), null);
syms.unnamedModule.complete(); // TEMP to force reading all named modules
modules.initModules(classTrees.toList(), Collections.emptySet(), Collections.emptySet());
// Build up the complete list of any packages to be documented
Location location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH
@ -386,8 +388,16 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
private Location getLocation(String packageName) throws IOException {
if (location == StandardLocation.MODULE_SOURCE_PATH) {
// TODO: handle invalid results
ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
return fm.getModuleLocation(location, msym.name.toString());
Name pack = names.fromString(packageName);
for (ModuleSymbol msym : modules.allModules()) {
PackageSymbol p = syms.getPackage(msym, pack);
if (p != null && !p.members().isEmpty()) {
return fm.getModuleLocation(location, msym.name.toString());
}
}
return null;
} else {
return location;
}

View File

@ -49,6 +49,7 @@ import com.sun.tools.javac.code.ClassFinder;
import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@ -56,6 +57,7 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
import jdk.javadoc.doclet.DocletEnvironment;
@ -187,9 +189,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
// Parse file objects provide via the DocumentationTool API
parse(fileObjects, classTrees, true);
modules.enter(classTrees.toList(), null);
syms.unnamedModule.complete(); // TEMP to force reading all named modules
modules.initModules(classTrees.toList(), Collections.emptySet(), Collections.emptySet());
// Build up the complete list of any packages to be documented
Location location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH
@ -394,11 +395,16 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
private Location getLocation(String packageName) throws IOException {
if (location == StandardLocation.MODULE_SOURCE_PATH) {
// TODO: handle invalid results better.
ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
if (msym == null) {
return null;
Name pack = names.fromString(packageName);
for (ModuleSymbol msym : modules.allModules()) {
PackageSymbol p = syms.getPackage(msym, pack);
if (p != null && !p.members().isEmpty()) {
return fm.getModuleLocation(location, msym.name.toString());
}
}
return fm.getModuleLocation(location, msym.name.toString());
return null;
} else {
return location;
}

View File

@ -44,9 +44,7 @@ import java.nio.channels.*;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.List;
import javax.tools.ToolProvider;
public class T6330997 {
@ -57,8 +55,7 @@ public class T6330997 {
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
Symtab syms = Symtab.instance(task.getContext());
Modules modules = Modules.instance(task.getContext());
modules.enter(List.nil(), null);
task.ensureEntered();
try {
compiler.resolveIdent(syms.unnamedModule, "T1").complete();
} catch (Exception e) {

View File

@ -38,9 +38,7 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.List;
import javax.tools.ToolProvider;
public class T6435291 {
@ -48,8 +46,7 @@ public class T6435291 {
javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
Symtab syms = Symtab.instance(task.getContext());
//initialize unnamed module:
Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
task.ensureEntered();
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
try {
compiler.resolveIdent(syms.unnamedModule, "T").complete();

View File

@ -41,17 +41,14 @@ import javax.tools.ToolProvider;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.List;
public class T6400303 {
public static void main(String... args) {
javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
Symtab syms = Symtab.instance(task.getContext());
//initialize unnamed module:
Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
task.ensureEntered();
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
try {
compiler.resolveIdent(syms.unnamedModule, "Test$1").complete();

View File

@ -36,9 +36,7 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.List;
import java.io.IOException;
import javax.tools.ToolProvider;
@ -54,8 +52,7 @@ public class TestResolveIdent {
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
Symtab syms = Symtab.instance(task.getContext());
Modules modules = Modules.instance(task.getContext());
modules.enter(List.nil(), null);
task.ensureEntered();
System.out.println(compiler.resolveIdent(syms.unnamedModule, getDeprecatedClass().getCanonicalName()));
}

View File

@ -42,11 +42,9 @@ import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.List;
import java.io.File;
import java.util.Arrays;
import java.util.Objects;
@ -74,8 +72,7 @@ public class BadClassfile {
JavacTaskImpl task = (JavacTaskImpl) c.getTask(null, null, null, Arrays.asList("-classpath", System.getProperty("test.classes", ".")), null, null);
Symtab syms = Symtab.instance(task.getContext());
//initialize unnamed module:
Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
task.ensureEntered();
try {
Symbol clazz = com.sun.tools.javac.main.JavaCompiler.instance(task.getContext()).resolveIdent(syms.unnamedModule, classname);

View File

@ -41,6 +41,7 @@ import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.CompileStates;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.Arguments;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@ -92,6 +93,7 @@ class ReusableContext extends Context implements TaskListener {
((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
Types.instance(this).newRound();
Check.instance(this).newRound();
Modules.instance(this).newRound();
CompileStates.instance(this).clear();
MultiTaskListener.instance(this).clear();

View File

@ -41,6 +41,7 @@ import com.sun.tools.javac.comp.Attr;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Infer;
import com.sun.tools.javac.comp.InferenceContext;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
@ -537,6 +538,7 @@ public class TypeHarness {
void clear() {
newRound();
Modules.instance(context).newRound();
}
}
// </editor-fold>