Skip to content
Permalink
Browse files
8274347: Passing a *nested* switch expression as a parameter causes a…
…n NPE during compile

Reviewed-by: vromero
  • Loading branch information
Jan Lahoda committed Oct 11, 2021
1 parent 110e38d commit b870468bdc99938fbb19a41b0ede0a3e3769ace2
@@ -1800,6 +1800,7 @@ private void handleSwitch(JCTree switchTree,
}
addVars(c.stats, switchEnv.info.scope);

preFlow(c);
c.completesNormally = flow.aliveAfter(caseEnv, c, make);

prevBindings = c.caseKind == CaseTree.CaseKind.STATEMENT && c.completesNormally ? currentBindings
@@ -5918,6 +5919,8 @@ public void visitVarDef(JCVariableDecl that) {

@Override
public void visitBindingPattern(JCBindingPattern that) {
initTypeIfNeeded(that);
initTypeIfNeeded(that.var);
if (that.var.sym == null) {
that.var.sym = new BindingSymbol(0, that.var.name, that.var.type, syms.noSymbol);
that.var.sym.adr = 0;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@

/*
* @test
* @bug 8205418 8207229 8207230 8230847 8245786 8247334 8248641 8240658 8246774
* @bug 8205418 8207229 8207230 8230847 8245786 8247334 8248641 8240658 8246774 8274347
* @summary Test the outcomes from Trees.getScope
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.comp
@@ -88,6 +88,7 @@ public static void main(String... args) throws IOException {
new TestGetScopeResult().testRecord();
new TestGetScopeResult().testLocalRecordAnnotation();
new TestGetScopeResult().testRuleCases();
new TestGetScopeResult().testNestedSwitchExpression();
}

public void run() throws IOException {
@@ -751,6 +752,77 @@ JCTree getCaseBody(Scope scope) {
}
}

void testNestedSwitchExpression() throws IOException {
JavacTool c = JavacTool.create();
try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
String code = """
class Test {
void t(Object o1, Object o2) {
System.err.println(switch (o1) {
case String s -> switch (j) {
case Integer i -> {
int scopeHere;
yield "";
}
default -> "";
};
default -> "";
});
}
}
""";
class MyFileObject extends SimpleJavaFileObject {
MyFileObject() {
super(URI.create("myfo:///Test.java"), SOURCE);
}
@Override
public String getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
Context ctx = new Context();
TestAnalyzer.preRegister(ctx);
JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null,
List.of(new MyFileObject()), ctx);
CompilationUnitTree cut = t.parse().iterator().next();
t.analyze();

List<List<String>> actual = new ArrayList<>();

new TreePathScanner<Void, Void>() {
@Override
public Void visitVariable(VariableTree node, Void p) {
if (node.getName().contentEquals("scopeHere")) {
Scope scope = Trees.instance(t).getScope(getCurrentPath());
actual.add(dumpScope(scope));
JCTree body = getCaseBody(scope);
if (body == null) {
throw new AssertionError("Unexpected null body.");
}
}
return super.visitVariable(node, p);
}
JCTree getCaseBody(Scope scope) {
return ((JCCase) ((JavacScope) scope).getEnv().next.next.tree).body;
}
}.scan(cut, null);

List<List<String>> expected =
List.of(List.of("scopeHere:int",
"i:java.lang.Integer",
"s:java.lang.String",
"o2:java.lang.Object",
"o1:java.lang.Object",
"super:java.lang.Object",
"this:Test"
));

if (!expected.equals(actual)) {
throw new AssertionError("Unexpected Scope content: " + actual);
}
}
}

private List<String> dumpScope(Scope scope) {
List<String> content = new ArrayList<>();
while (scope.getEnclosingClass() != null) {
@@ -1,6 +1,6 @@
/*
* @test /nodynamiccopyright/
* @bug 8206986 8254286
* @bug 8206986 8254286 8274347
* @summary Check types inferred for switch expressions.
* @compile/fail/ref=ExpressionSwitchInfer.out -XDrawDiagnostics ExpressionSwitchInfer.java
*/
@@ -83,4 +83,14 @@ void bug8254286(I1 i1, I2 i2, int s) {
interface I1 extends I {}
interface I2 extends I {}

void preflow(int i, int j) {
System.out.println(switch (i) {
case 1 -> switch (j) {
case 1 -> "one and one";
default -> "one and many";
};
case 2 -> "two";
default -> "many";
});
}
}

3 comments on commit b870468

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot replied Oct 11, 2021

@kvergizova

This comment has been minimized.

Copy link
Contributor

@kvergizova kvergizova replied Oct 15, 2021

/backport jdk17u

@openjdk

This comment has been minimized.

Copy link

@openjdk openjdk bot replied Oct 15, 2021

@kvergizova @kvergizova the backport was successfully created on the branch kvergizova-backport-b870468b in my personal fork of openjdk/jdk17u. To create a pull request with this backport targeting openjdk/jdk17u:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

this pull request contains a backport of commit b870468b from the openjdk/jdk repository.

The commit being backported was authored by Jan Lahoda on 11 Oct 2021 and was reviewed by Vicente Romero.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk17u:

$ git fetch https://github.com/openjdk-bots/jdk17u kvergizova-backport-b870468b:kvergizova-backport-b870468b
$ git checkout kvergizova-backport-b870468b
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk17u kvergizova-backport-b870468b
Please sign in to comment.