Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
Original file line number Diff line number Diff line change
Expand Up @@ -5634,12 +5634,16 @@ private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
chk.validateRepeatable(c, repeatable, cbPos);
}
} else {
// Check that all extended classes and interfaces
// are compatible (i.e. no two define methods with same arguments
// yet different return types). (JLS 8.4.8.3)
chk.checkCompatibleSupertypes(tree.pos(), c.type);
chk.checkDefaultMethodClashes(tree.pos(), c.type);
chk.checkPotentiallyAmbiguousOverloads(tree, c.type);
try {
// Check that all extended classes and interfaces
// are compatible (i.e. no two define methods with same arguments
// yet different return types). (JLS 8.4.8.3)
chk.checkCompatibleSupertypes(tree.pos(), c.type);
chk.checkDefaultMethodClashes(tree.pos(), c.type);
chk.checkPotentiallyAmbiguousOverloads(tree, c.type);
} catch (CompletionFailure cf) {
chk.completionError(tree.pos(), cf);
}
}

// Check that class does not import the same parameterized interface
Expand Down
158 changes: 157 additions & 1 deletion test/langtools/tools/javac/recovery/AttrRecovery.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

/*
* @test
* @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336
* @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 8373094
* @summary Verify error recovery w.r.t. Attr
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
Expand All @@ -32,20 +32,25 @@
* @run main AttrRecovery
*/

import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
Expand Down Expand Up @@ -495,4 +500,155 @@ private void verifyElement() {
}
}
}

@Test //JDK-8373094
public void testSensibleAttribution() throws Exception {
Path curPath = Path.of(".");
Path lib = curPath.resolve("lib");
Path classes = lib.resolve("classes");
Files.createDirectories(classes);
new JavacTask(tb)
.outdir(classes)
.sources("""
package test;
public class Intermediate<T> extends Base<T> {}
""",
"""
package test;
public class Base<T> {
public void t(Missing<T> m) {}
}
""",
"""
package test;
public class Missing<T> {
}
""")
.run()
.writeAll();

Files.delete(classes.resolve("test").resolve("Missing.class"));

record TestCase(String code, List<String> options, String... expectedErrors) {}
TestCase[] testCases = new TestCase[] {
new TestCase("""
package test;
public class Test extends Intermediate<String> {
private void test() {
int i = 0;
System.err.println(i);
while (true) {
break;
}
}
}
""",
List.of(),
"Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)",
"1 error"),
new TestCase("""
package test;
public class Test extends Intermediate<String> {
private void test() {
int i = 0;
System.err.println(i);
while (true) {
break;
}
}
}
""",
List.of("-XDshould-stop.at=FLOW"),
"Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)",
"1 error"),
};

for (TestCase tc : testCases) {
List<String> attributes = new ArrayList<>();
List<String> actual = new JavacTask(tb)
.options(Stream.concat(List.of("-XDrawDiagnostics", "-XDdev").stream(),
tc.options.stream()).toList())
.classpath(classes)
.sources(tc.code())
.outdir(curPath)
.callback(task -> {
task.addTaskListener(new TaskListener() {
@Override
public void finished(TaskEvent e) {
if (e.getKind() != TaskEvent.Kind.ANALYZE) {
return ;
}
Trees trees = Trees.instance(task);
new TreePathScanner<Void, Void>() {
boolean check;

@Override
public Void visitMethod(MethodTree node, Void p) {
if (node.getName().contentEquals("test")) {
check = true;
try {
return super.visitMethod(node, p);
} finally {
check = false;
}
}

return super.visitMethod(node, p);
}

@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
if (!node.toString().contains("super")) {
verifyElement();
}
return super.visitMethodInvocation(node, p);
}

@Override
public Void visitIdentifier(IdentifierTree node, Void p) {
verifyElement();
return super.visitIdentifier(node, p);
}

@Override
public Void visitMemberSelect(MemberSelectTree node, Void p) {
verifyElement();
return super.visitMemberSelect(node, p);
}

private void verifyElement() {
if (!check) {
return ;
}

Element el = trees.getElement(getCurrentPath());
if (el == null) {
error("Unattributed tree: " + getCurrentPath().getLeaf());
} else {
attributes.add(el.toString());
}
}
}.scan(e.getCompilationUnit(), null);
}
});
})
.run(Expect.FAIL)
.writeAll()
.getOutputLines(OutputKind.DIRECT);

List<String> expectedErrors = List.of(tc.expectedErrors);

if (!Objects.equals(actual, expectedErrors)) {
error("Expected: " + expectedErrors + ", but got: " + actual);
}

List<String> expectedAttributes =
List.of("println(int)", "println(int)", "err", "java.lang.System", "i");

if (!Objects.equals(attributes, expectedAttributes)) {
error("Expected: " + expectedAttributes + ", but got: " + attributes);
}
}
}

}