提交 82c8d34d 编写于 作者: K ksrini

8017216: javac doesn't fill in end position for some errors of type not found

8019421: Javac doesn't fill in end position for some annotation related errors
8019422: Javac doesn't fill in end position for uninitialized variable errors
Reviewed-by: jjg, mcimadamore
上级 99e664af
...@@ -273,7 +273,7 @@ public class Annotate { ...@@ -273,7 +273,7 @@ public class Annotate {
continue; continue;
} }
JCIdent left = (JCIdent)assign.lhs; JCIdent left = (JCIdent)assign.lhs;
Symbol method = rs.resolveQualifiedMethod(left.pos(), Symbol method = rs.resolveQualifiedMethod(assign.rhs.pos(),
env, env,
a.type, a.type,
left.name, left.name,
......
...@@ -1948,6 +1948,8 @@ public class Attr extends JCTree.Visitor { ...@@ -1948,6 +1948,8 @@ public class Attr extends JCTree.Visitor {
clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), clazzid1 = make.at(clazz.pos).Select(make.Type(encltype),
((JCIdent) clazzid).name); ((JCIdent) clazzid).name);
EndPosTable endPosTable = this.env.toplevel.endPositions;
endPosTable.storeEnd(clazzid1, tree.getEndPosition(endPosTable));
if (clazz.hasTag(ANNOTATED_TYPE)) { if (clazz.hasTag(ANNOTATED_TYPE)) {
JCAnnotatedType annoType = (JCAnnotatedType) clazz; JCAnnotatedType annoType = (JCAnnotatedType) clazz;
List<JCAnnotation> annos = annoType.annotations; List<JCAnnotation> annos = annoType.annotations;
......
...@@ -1339,7 +1339,7 @@ public class Flow { ...@@ -1339,7 +1339,7 @@ public class Flow {
/** A mapping from addresses to variable symbols. /** A mapping from addresses to variable symbols.
*/ */
VarSymbol[] vars; JCVariableDecl[] vardecls;
/** The current class being defined. /** The current class being defined.
*/ */
...@@ -1417,13 +1417,14 @@ public class Flow { ...@@ -1417,13 +1417,14 @@ public class Flow {
* to the next available sequence number and entering it under that * to the next available sequence number and entering it under that
* index into the vars array. * index into the vars array.
*/ */
void newVar(VarSymbol sym) { void newVar(JCVariableDecl varDecl) {
vars = ArrayUtils.ensureCapacity(vars, nextadr); VarSymbol sym = varDecl.sym;
vardecls = ArrayUtils.ensureCapacity(vardecls, nextadr);
if ((sym.flags() & FINAL) == 0) { if ((sym.flags() & FINAL) == 0) {
sym.flags_field |= EFFECTIVELY_FINAL; sym.flags_field |= EFFECTIVELY_FINAL;
} }
sym.adr = nextadr; sym.adr = nextadr;
vars[nextadr] = sym; vardecls[nextadr] = varDecl;
inits.excl(nextadr); inits.excl(nextadr);
uninits.incl(nextadr); uninits.incl(nextadr);
nextadr++; nextadr++;
...@@ -1493,11 +1494,13 @@ public class Flow { ...@@ -1493,11 +1494,13 @@ public class Flow {
/** Check that trackable variable is initialized. /** Check that trackable variable is initialized.
*/ */
void checkInit(DiagnosticPosition pos, VarSymbol sym) { void checkInit(DiagnosticPosition pos, VarSymbol sym) {
checkInit(pos, sym, "var.might.not.have.been.initialized");
}
void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
if ((sym.adr >= firstadr || sym.owner.kind != TYP) && if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
trackable(sym) && trackable(sym) &&
!inits.isMember(sym.adr)) { !inits.isMember(sym.adr)) {
log.error(pos, "var.might.not.have.been.initialized", log.error(pos, errkey, sym);
sym);
inits.incl(sym.adr); inits.incl(sym.adr);
} }
} }
...@@ -1599,7 +1602,7 @@ public class Flow { ...@@ -1599,7 +1602,7 @@ public class Flow {
if ((def.mods.flags & STATIC) != 0) { if ((def.mods.flags & STATIC) != 0) {
VarSymbol sym = def.sym; VarSymbol sym = def.sym;
if (trackable(sym)) if (trackable(sym))
newVar(sym); newVar(def);
} }
} }
} }
...@@ -1619,7 +1622,7 @@ public class Flow { ...@@ -1619,7 +1622,7 @@ public class Flow {
if ((def.mods.flags & STATIC) == 0) { if ((def.mods.flags & STATIC) == 0) {
VarSymbol sym = def.sym; VarSymbol sym = def.sym;
if (trackable(sym)) if (trackable(sym))
newVar(sym); newVar(def);
} }
} }
} }
...@@ -1678,9 +1681,22 @@ public class Flow { ...@@ -1678,9 +1681,22 @@ public class Flow {
scan(tree.body); scan(tree.body);
if (isInitialConstructor) { if (isInitialConstructor) {
for (int i = firstadr; i < nextadr; i++) boolean isSynthesized = (tree.sym.flags() &
if (vars[i].owner == classDef.sym) GENERATEDCONSTR) != 0;
checkInit(TreeInfo.diagEndPos(tree.body), vars[i]); for (int i = firstadr; i < nextadr; i++) {
JCVariableDecl vardecl = vardecls[i];
VarSymbol var = vardecl.sym;
if (var.owner == classDef.sym) {
// choose the diagnostic position based on whether
// the ctor is default(synthesized) or not
if (isSynthesized) {
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
var, "var.not.initialized.in.default.constructor");
} else {
checkInit(TreeInfo.diagEndPos(tree.body), var);
}
}
}
} }
List<AssignPendingExit> exits = pendingExits.toList(); List<AssignPendingExit> exits = pendingExits.toList();
pendingExits = new ListBuffer<AssignPendingExit>(); pendingExits = new ListBuffer<AssignPendingExit>();
...@@ -1691,7 +1707,7 @@ public class Flow { ...@@ -1691,7 +1707,7 @@ public class Flow {
if (isInitialConstructor) { if (isInitialConstructor) {
inits.assign(exit.exit_inits); inits.assign(exit.exit_inits);
for (int i = firstadr; i < nextadr; i++) for (int i = firstadr; i < nextadr; i++)
checkInit(exit.tree.pos(), vars[i]); checkInit(exit.tree.pos(), vardecls[i].sym);
} }
} }
} finally { } finally {
...@@ -1706,7 +1722,7 @@ public class Flow { ...@@ -1706,7 +1722,7 @@ public class Flow {
public void visitVarDef(JCVariableDecl tree) { public void visitVarDef(JCVariableDecl tree) {
boolean track = trackable(tree.sym); boolean track = trackable(tree.sym);
if (track && tree.sym.owner.kind == MTH) newVar(tree.sym); if (track && tree.sym.owner.kind == MTH) newVar(tree);
if (tree.init != null) { if (tree.init != null) {
Lint lintPrev = lint; Lint lintPrev = lint;
lint = lint.augment(tree.sym); lint = lint.augment(tree.sym);
...@@ -2239,11 +2255,11 @@ public class Flow { ...@@ -2239,11 +2255,11 @@ public class Flow {
Flow.this.make = make; Flow.this.make = make;
startPos = tree.pos().getStartPosition(); startPos = tree.pos().getStartPosition();
if (vars == null) if (vardecls == null)
vars = new VarSymbol[32]; vardecls = new JCVariableDecl[32];
else else
for (int i=0; i<vars.length; i++) for (int i=0; i<vardecls.length; i++)
vars[i] = null; vardecls[i] = null;
firstadr = 0; firstadr = 0;
nextadr = 0; nextadr = 0;
pendingExits = new ListBuffer<AssignPendingExit>(); pendingExits = new ListBuffer<AssignPendingExit>();
...@@ -2255,8 +2271,8 @@ public class Flow { ...@@ -2255,8 +2271,8 @@ public class Flow {
startPos = -1; startPos = -1;
resetBits(inits, uninits, uninitsTry, initsWhenTrue, resetBits(inits, uninits, uninitsTry, initsWhenTrue,
initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse); initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
if (vars != null) for (int i=0; i<vars.length; i++) if (vardecls != null) for (int i=0; i<vardecls.length; i++)
vars[i] = null; vardecls[i] = null;
firstadr = 0; firstadr = 0;
nextadr = 0; nextadr = 0;
pendingExits = null; pendingExits = null;
......
...@@ -4053,7 +4053,7 @@ public class JavacParser implements Parser { ...@@ -4053,7 +4053,7 @@ public class JavacParser implements Parser {
endPosMap = new HashMap<JCTree, Integer>(); endPosMap = new HashMap<JCTree, Integer>();
} }
protected void storeEnd(JCTree tree, int endpos) { public void storeEnd(JCTree tree, int endpos) {
endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos); endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
} }
...@@ -4091,7 +4091,7 @@ public class JavacParser implements Parser { ...@@ -4091,7 +4091,7 @@ public class JavacParser implements Parser {
super(parser); super(parser);
} }
protected void storeEnd(JCTree tree, int endpos) { /* empty */ } public void storeEnd(JCTree tree, int endpos) { /* empty */ }
protected <T extends JCTree> T to(T t) { protected <T extends JCTree> T to(T t) {
return t; return t;
...@@ -4126,14 +4126,6 @@ public class JavacParser implements Parser { ...@@ -4126,14 +4126,6 @@ public class JavacParser implements Parser {
this.parser = parser; this.parser = parser;
} }
/**
* Store ending position for a tree, the value of which is the greater
* of last error position and the given ending position.
* @param tree The tree.
* @param endpos The ending position to associate with the tree.
*/
protected abstract void storeEnd(JCTree tree, int endpos);
/** /**
* Store current token's ending position for a tree, the value of which * Store current token's ending position for a tree, the value of which
* will be the greater of last error position and the ending position of * will be the greater of last error position and the ending position of
......
...@@ -1068,6 +1068,10 @@ compiler.err.var.might.already.be.assigned=\ ...@@ -1068,6 +1068,10 @@ compiler.err.var.might.already.be.assigned=\
compiler.err.var.might.not.have.been.initialized=\ compiler.err.var.might.not.have.been.initialized=\
variable {0} might not have been initialized variable {0} might not have been initialized
# 0: symbol
compiler.err.var.not.initialized.in.default.constructor=\
variable {0} not initialized in the default constructor
# 0: symbol # 0: symbol
compiler.err.var.might.be.assigned.in.loop=\ compiler.err.var.might.be.assigned.in.loop=\
variable {0} might be assigned in loop variable {0} might be assigned in loop
......
/* /*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -42,11 +42,18 @@ public interface EndPosTable { ...@@ -42,11 +42,18 @@ public interface EndPosTable {
*/ */
public int getEndPos(JCTree tree); public int getEndPos(JCTree tree);
/**
* Store ending position for a tree, the value of which is the greater of
* last error position and the given ending position.
* @param tree The tree.
* @param endpos The ending position to associate with the tree.
*/
public abstract void storeEnd(JCTree tree, int endpos);
/** /**
* Give an old tree and a new tree, the old tree will be replaced with * Give an old tree and a new tree, the old tree will be replaced with
* the new tree, the position of the new tree will be that of the old * the new tree, the position of the new tree will be that of the old
* tree. * tree.
* not exist.
* @param oldtree a JCTree to be replaced * @param oldtree a JCTree to be replaced
* @param newtree a JCTree to be replaced with * @param newtree a JCTree to be replaced with
* @return position of the old tree or Positions.NOPOS for non-existent mapping * @return position of the old tree or Positions.NOPOS for non-existent mapping
......
/*
* Copyright (c) 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.var.not.initialized.in.default.constructor
class X {
final int j;
}
/*
* Copyright (c) 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8017216 8019422 8019421
* @summary verify start and end positions
* @run main TreeEndPosTest
*/
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
public class TreeEndPosTest {
private static JavaFileManager getJavaFileManager(JavaCompiler compiler,
DiagnosticCollector dc) {
return compiler.getStandardFileManager(dc, null, null);
}
static class JavaSource extends SimpleJavaFileObject {
final String source;
int startPos;
int endPos;
private JavaSource(String filename, String source) {
super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
this.source = source;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
static JavaSource createJavaSource(String preamble, String body,
String postamble, String expected) {
JavaSource js = createJavaSource(preamble, body, postamble, -1, -1);
js.startPos = js.source.indexOf(expected);
js.endPos = js.startPos + expected.length();
return js;
}
static JavaSource createJavaSource(String body, String expected) {
return createJavaSource(null, body, null, expected);
}
private static JavaSource createJavaSource(String preamble, String body,
String postamble, int start, int end) {
final String name = "Bug";
StringBuilder code = new StringBuilder();
if (preamble != null) {
code.append(preamble);
}
code.append("public class " + name + "{");
if (body != null) {
code.append(body);
}
code.append("}");
if (postamble != null) {
code.append(postamble);
}
JavaSource js = new JavaSource(name + ".java", code.toString());
js.startPos = start;
js.endPos = end;
return js;
}
}
public static void main(String... args) throws IOException {
testUninitializedVariable();
testMissingAnnotationValue();
testFinalVariableWithDefaultConstructor();
testFinalVariableWithConstructor();
}
static void testUninitializedVariable() throws IOException {
compile(JavaSource.createJavaSource("Object o = new A().new B(); class A { }",
"B()"));
}
static void testMissingAnnotationValue() throws IOException {
compile(JavaSource.createJavaSource("@Foo(\"vvvv\")",
null, "@interface Foo { }", "\"vvvv\""));
}
static void testFinalVariableWithDefaultConstructor() throws IOException {
compile(JavaSource.createJavaSource("private static final String Foo; public void bar() { }",
"private static final String Foo;"));
}
static void testFinalVariableWithConstructor() throws IOException {
compile(JavaSource.createJavaSource("public Bug (){} private static final String Foo; public void bar() { }",
"{}"));
}
static void compile(JavaSource src) throws IOException {
ByteArrayOutputStream ba = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(ba);
File tempDir = new File(".");
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector dc = new DiagnosticCollector();
JavaFileManager javaFileManager = getJavaFileManager(compiler, dc);
List<String> options = new ArrayList<>();
options.add("-cp");
options.add(tempDir.getPath());
options.add("-d");
options.add(tempDir.getPath());
options.add("-XDshouldStopPolicy=GENERATE");
List<JavaFileObject> sources = new ArrayList<>();
sources.add(src);
JavaCompiler.CompilationTask task =
compiler.getTask(writer, javaFileManager,
dc, options, null,
sources);
task.call();
for (Diagnostic diagnostic : (List<Diagnostic>) dc.getDiagnostics()) {
long actualStart = diagnostic.getStartPosition();
long actualEnd = diagnostic.getEndPosition();
System.out.println("Source: " + src.source);
System.out.println("Diagnostic: " + diagnostic);
System.out.print("Start position: Expected: " + src.startPos);
System.out.println(", Actual: " + actualStart);
System.out.print("End position: Expected: " + src.endPos);
System.out.println(", Actual: " + actualEnd);
if (src.startPos != actualStart || src.endPos != actualEnd) {
throw new RuntimeException("error: trees don't match");
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册