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

Backport-of: b870468bdc99938fbb19a41b0ede0a3e3769ace2
  • Loading branch information
Ekaterina Vergizova authored and Yuri Nesterenko committed Oct 18, 2021
1 parent 6081dca commit ee02c6426769ef15578ae2505658a401d1f13469
@@ -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
@@ -5914,6 +5915,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";
});
}
}

1 comment on commit ee02c64

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on ee02c64 Oct 18, 2021

Please sign in to comment.