# HG changeset patch # User jlahoda # Date 1531491672 -7200 # Fri Jul 13 16:21:12 2018 +0200 # Node ID a59eef9740bd6f8f3b884c5fc6dd02e84de044bd # Parent 3f51ddbe48434e6f9ba2ee3233e21279769839ed 8207229: Trees.getScope crashes for broken lambda 8207230: Trees.getScope runs Analyzers Reviewed-by: TBD diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java @@ -475,7 +475,7 @@ * Analyze an AST node; this involves collecting a list of all the nodes that needs rewriting, * and speculatively type-check the rewritten code to compare results against previously attributed code. */ - void analyze(JCStatement statement, Env env) { + protected void analyze(JCStatement statement, Env env) { StatementScanner statementScanner = new StatementScanner(statement, env); statementScanner.scan(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -71,6 +71,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.TypeTag.WILDCARD; +import com.sun.tools.javac.comp.Analyzer.AnalyzerMode; import static com.sun.tools.javac.tree.JCTree.Tag.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; @@ -396,7 +397,9 @@ public Env attribExprToTree(JCTree expr, Env env, JCTree tree) { breakTree = tree; JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + EnumSet analyzerModes = EnumSet.copyOf(analyzer.analyzerModes); try { + analyzer.analyzerModes.clear(); attribExpr(expr, env); } catch (BreakAttr b) { return b.env; @@ -409,6 +412,7 @@ } finally { breakTree = null; log.useSource(prev); + analyzer.analyzerModes.addAll(analyzerModes); } return env; } @@ -416,7 +420,9 @@ public Env attribStatToTree(JCTree stmt, Env env, JCTree tree) { breakTree = tree; JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + EnumSet analyzerModes = EnumSet.copyOf(analyzer.analyzerModes); try { + analyzer.analyzerModes.clear(); attribStat(stmt, env); } catch (BreakAttr b) { return b.env; @@ -429,6 +435,7 @@ } finally { breakTree = null; log.useSource(prev); + analyzer.analyzerModes.addAll(analyzerModes); } return env; } @@ -2762,7 +2769,7 @@ JCLambda lambda = (JCLambda)tree; List argtypes = List.nil(); for (JCVariableDecl param : lambda.params) { - argtypes = param.vartype != null ? + argtypes = param.vartype != null && param.vartype.type != null ? argtypes.append(param.vartype.type) : argtypes.append(syms.errType); } diff --git a/test/langtools/tools/javac/api/TestGetScopeResult.java b/test/langtools/tools/javac/api/TestGetScopeResult.java --- a/test/langtools/tools/javac/api/TestGetScopeResult.java +++ b/test/langtools/tools/javac/api/TestGetScopeResult.java @@ -23,9 +23,12 @@ /* * @test - * @bug 8205418 + * @bug 8205418 8207229 8207230 * @summary Test the outcomes from Trees.getScope - * @modules jdk.compiler + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util */ import java.io.IOException; @@ -42,16 +45,26 @@ import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.LambdaExpressionTree; import com.sun.source.tree.Scope; +import com.sun.source.tree.VariableTree; import com.sun.source.util.JavacTask; import com.sun.source.util.TreePath; import com.sun.source.util.TreePathScanner; import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.comp.Analyzer; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; + import static javax.tools.JavaFileObject.Kind.SOURCE; public class TestGetScopeResult { public static void main(String... args) throws IOException { new TestGetScopeResult().run(); + new TestGetScopeResult().testAnalyzerDisabled(); } public void run() throws IOException { @@ -109,6 +122,26 @@ }; doTest("class Test { void test() { cand1(s -> { }); } void cand1(I1 i) { } void cand1(I2 i, int i) { } interface I1 { public String test(String s); } interface I2 { public int test(CharSequence s); } }", multipleCandidates2); + + String[] implicitExplicitConflict1 = { + ":t", + "s:java.lang.String", + "super:java.lang.Object", + "this:Test" + }; + + doTest("class Test { void test() { cand((var s, t) -> \"\"); } void cand(I i) { } interface I { public String test(String s); } }", + implicitExplicitConflict1); + + String[] implicitExplicitConflict2 = { + "s:", + ":t", + "super:java.lang.Object", + "this:Test" + }; + + doTest("class Test { void test() { cand((t, var s) -> \"\"); } void cand(I i) { } interface I { public String test(String s); } }", + implicitExplicitConflict2); } public void doTest(String code, String... expected) throws IOException { @@ -151,5 +184,79 @@ } } + void testAnalyzerDisabled() throws IOException { + JavacTool c = JavacTool.create(); + try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { + class MyFileObject extends SimpleJavaFileObject { + MyFileObject() { + super(URI.create("myfo:///Test.java"), SOURCE); + } + @Override + public String getCharContent(boolean ignoreEncodingErrors) { + return "class Test {" + + " void test() { cand(() -> { System.err.println(); }); }" + + " Runnable r = new Runnable() { public void test() { System.err.println(); } };" + + " void cand(Runnable r) { }" + + "}"; + } + } + Context ctx = new Context(); + TestAnalyzer.preRegister(ctx); + JavacTask t = (JavacTask) c.getTask(null, fm, null, List.of("-XDfind=lambda"), null, + List.of(new MyFileObject()), ctx); + CompilationUnitTree cut = t.parse().iterator().next(); + t.analyze(); + + TestAnalyzer analyzer = (TestAnalyzer) TestAnalyzer.instance(ctx); + + if (!analyzer.analyzeCalled) { + throw new IllegalStateException("Analyzer didn't run!"); + } + + new TreePathScanner() { + @Override + public Void visitLambdaExpression(LambdaExpressionTree node, Void p) { + analyzer.analyzeCalled = false; + Trees.instance(t).getScope(new TreePath(getCurrentPath(), node.getBody())); + if (analyzer.analyzeCalled) { + throw new IllegalStateException("Analyzer was run during getScope!"); + } + return super.visitLambdaExpression(node, p); + } + + @Override + public Void visitVariable(VariableTree node, Void p) { + if (node.getInitializer() != null) { + analyzer.analyzeCalled = false; + TreePath tp = new TreePath(getCurrentPath(), node.getInitializer()); + Trees.instance(t).getScope(tp); + if (analyzer.analyzeCalled) { + throw new IllegalStateException("Analyzer was run during getScope!"); + } + } + return super.visitVariable(node, p); + } + }.scan(cut, null); + } + } + + private static final class TestAnalyzer extends Analyzer { + + public static void preRegister(Context context) { + context.put(analyzerKey, (Factory) ctx -> new TestAnalyzer(ctx)); + } + + private boolean analyzeCalled; + + public TestAnalyzer(Context context) { + super(context); + } + + @Override + protected void analyze(JCStatement statement, Env env) { + analyzeCalled = true; + super.analyze(statement, env); + } + } }