8145466: javac: No line numbers in compilation error
Summary: Compiler should not use the syntax tree from enclosing contexts in diagnostics even when the enclosing contexts are consulted for method lookup.
Reviewed-by: mcimadamore
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Wed Jul 05 21:09:59 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Tue Dec 22 16:37:52 2015 +0530
@@ -25,6 +25,7 @@
package com.sun.tools.javac.comp;
+import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -95,6 +96,13 @@
*/
Type defaultSuperCallSite = null;
+ /** Tree that when non null, is to be preferentially used in diagnostics.
+ * Usually Env<AttrContext>.tree is the tree to be referred to in messages,
+ * but this may not be true during the window a method is looked up in enclosing
+ * contexts (JDK-8145466)
+ */
+ JCTree preferredTreeForDiagnostics;
+
/** Duplicate this context, replacing scope field and copying all others.
*/
AttrContext dup(WriteableScope scope) {
@@ -112,6 +120,7 @@
info.isSpeculative = isSpeculative;
info.isAnonymousDiamond = isAnonymousDiamond;
info.isNewClass = isNewClass;
+ info.preferredTreeForDiagnostics = preferredTreeForDiagnostics;
return info;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 21:09:59 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Dec 22 16:37:52 2015 +0530
@@ -722,7 +722,8 @@
Warner warn) {
//should we expand formals?
boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
- List<JCExpression> trees = TreeInfo.args(env.tree);
+ JCTree callTree = treeForDiagnostics(env);
+ List<JCExpression> trees = TreeInfo.args(callTree);
//inference context used during this method check
InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
@@ -731,7 +732,7 @@
if (varargsFormal == null &&
argtypes.size() != formals.size()) {
- reportMC(env.tree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+ reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
@@ -743,7 +744,7 @@
}
if (formals.head != varargsFormal) {
- reportMC(env.tree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+ reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
if (useVarargs) {
@@ -759,6 +760,11 @@
}
}
+ // where
+ private JCTree treeForDiagnostics(Env<AttrContext> env) {
+ return env.info.preferredTreeForDiagnostics != null ? env.info.preferredTreeForDiagnostics : env.tree;
+ }
+
/**
* Does the actual argument conforms to the corresponding formal?
*/
@@ -1847,17 +1853,23 @@
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1)) staticOnly = true;
- Symbol sym = findMethod(
- env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
- allowBoxing, useVarargs);
- if (sym.exists()) {
- if (staticOnly &&
- sym.kind == MTH &&
- sym.owner.kind == TYP &&
- (sym.flags() & STATIC) == 0) return new StaticError(sym);
- else return sym;
- } else {
- bestSoFar = bestOf(bestSoFar, sym);
+ Assert.check(env1.info.preferredTreeForDiagnostics == null);
+ env1.info.preferredTreeForDiagnostics = env.tree;
+ try {
+ Symbol sym = findMethod(
+ env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
+ allowBoxing, useVarargs);
+ if (sym.exists()) {
+ if (staticOnly &&
+ sym.kind == MTH &&
+ sym.owner.kind == TYP &&
+ (sym.flags() & STATIC) == 0) return new StaticError(sym);
+ else return sym;
+ } else {
+ bestSoFar = bestOf(bestSoFar, sym);
+ }
+ } finally {
+ env1.info.preferredTreeForDiagnostics = null;
}
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
env1 = env1.outer;
@@ -4184,7 +4196,11 @@
DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
DiagnosticType preferredKind, JCDiagnostic d) {
JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex];
- return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(),
+ DiagnosticPosition pos = d.getDiagnosticPosition();
+ if (pos == null) {
+ pos = preferedPos;
+ }
+ return diags.create(preferredKind, preferredSource, pos,
"prob.found.req", cause);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest.java Tue Dec 22 16:37:52 2015 +0530
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8145466
+ * @summary javac: No line numbers in compilation error
+ * @compile/fail/ref=DiagnosticRewriterTest.out -Xdiags:compact -XDrawDiagnostics DiagnosticRewriterTest.java
+ */
+
+class DiagnosticRewriterTest {
+ void test() {
+ new Object() {
+ void g() {
+ m(2L);
+ }
+ };
+ }
+
+ void m(int i) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest.out Tue Dec 22 16:37:52 2015 +0530
@@ -0,0 +1,3 @@
+DiagnosticRewriterTest.java:12:15: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: long, int)
+- compiler.note.compressed.diags
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest2.java Tue Dec 22 16:37:52 2015 +0530
@@ -0,0 +1,22 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8145466
+ * @summary javac: No line numbers in compilation error
+ * @compile/fail/ref=DiagnosticRewriterTest2.out -Xdiags:compact -XDrawDiagnostics DiagnosticRewriterTest2.java
+ */
+
+class DiagnosticRewriterTest2 {
+ class Bar {
+ Bar(Object o) { }
+ }
+ void test() {
+ new Bar(null) {
+ void g() {
+ m(2L);
+ m();
+ }
+ };
+ }
+
+ void m(int i) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest2.out Tue Dec 22 16:37:52 2015 +0530
@@ -0,0 +1,4 @@
+DiagnosticRewriterTest2.java:15:15: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: long, int)
+DiagnosticRewriterTest2.java:16:13: compiler.err.cant.apply.symbol: kindname.method, m, int, compiler.misc.no.args, kindname.class, DiagnosticRewriterTest2, (compiler.misc.arg.length.mismatch)
+- compiler.note.compressed.diags
+2 errors