Mercurial > hg > icedtea9-forest > langtools
changeset 1282:c35b158e2290
Merge
author | lana |
---|---|
date | Tue, 10 Apr 2012 23:19:26 -0700 |
parents | 9c429f38ca7e (diff) 517f0789bd4e (current diff) |
children | 6f0ed5a89c25 |
files | |
diffstat | 7 files changed, 422 insertions(+), 91 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Apr 09 21:58:05 2012 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue Apr 10 23:19:26 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -1798,92 +1798,126 @@ */ @SuppressWarnings("fallthrough") List<JCStatement> blockStatements() { -//todo: skip to anchor on error(?) - int lastErrPos = -1; + //todo: skip to anchor on error(?) ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); while (true) { - int pos = token.pos; - switch (token.kind) { - case RBRACE: case CASE: case DEFAULT: case EOF: + List<JCStatement> stat = blockStatement(); + if (stat.isEmpty()) { return stats.toList(); - case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: - case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: - case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: - stats.append(parseStatement()); + } else { + if (token.pos <= endPosTable.errorEndPos) { + skip(false, true, true, true); + } + stats.addAll(stat); + } + } + } + + /* + * This method parses a statement treating it as a block, relaxing the + * JLS restrictions, allows us to parse more faulty code, doing so + * enables us to provide better and accurate diagnostics to the user. + */ + JCStatement parseStatementAsBlock() { + int pos = token.pos; + List<JCStatement> stats = blockStatement(); + if (stats.isEmpty()) { + JCErroneous e = F.at(pos).Erroneous(); + error(e, "illegal.start.of.stmt"); + return F.at(pos).Exec(e); + } else { + JCStatement first = stats.head; + String error = null; + switch (first.getTag()) { + case CLASSDEF: + error = "class.not.allowed"; break; - case MONKEYS_AT: - case FINAL: { - String dc = token.comment(CommentStyle.JAVADOC); - JCModifiers mods = modifiersOpt(); - if (token.kind == INTERFACE || - token.kind == CLASS || - allowEnums && token.kind == ENUM) { - stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); - } else { - JCExpression t = parseType(); - stats.appendList(variableDeclarators(mods, t, - new ListBuffer<JCStatement>())); - // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon - storeEnd(stats.elems.last(), token.endPos); - accept(SEMI); - } - break; - } - case ABSTRACT: case STRICTFP: { - String dc = token.comment(CommentStyle.JAVADOC); - JCModifiers mods = modifiersOpt(); - stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); + case VARDEF: + error = "variable.not.allowed"; break; } - case INTERFACE: - case CLASS: - String dc = token.comment(CommentStyle.JAVADOC); - stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); - break; - case ENUM: - case ASSERT: - if (allowEnums && token.kind == ENUM) { - error(token.pos, "local.enum"); - dc = token.comment(CommentStyle.JAVADOC); - stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); - break; - } else if (allowAsserts && token.kind == ASSERT) { - stats.append(parseStatement()); - break; - } - /* fall through to default */ - default: - Token prevToken = token; - JCExpression t = term(EXPR | TYPE); - if (token.kind == COLON && t.hasTag(IDENT)) { - nextToken(); - JCStatement stat = parseStatement(); - stats.append(F.at(pos).Labelled(prevToken.name(), stat)); - } else if ((lastmode & TYPE) != 0 && - (token.kind == IDENTIFIER || - token.kind == ASSERT || - token.kind == ENUM)) { - pos = token.pos; - JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); - F.at(pos); - stats.appendList(variableDeclarators(mods, t, - new ListBuffer<JCStatement>())); - // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon - storeEnd(stats.elems.last(), token.endPos); - accept(SEMI); - } else { - // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon - stats.append(to(F.at(pos).Exec(checkExprStat(t)))); - accept(SEMI); - } + if (error != null) { + error(first, error); + List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats)); + return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist))); + } + return first; + } + } + + @SuppressWarnings("fallthrough") + List<JCStatement> blockStatement() { + //todo: skip to anchor on error(?) + int pos = token.pos; + switch (token.kind) { + case RBRACE: case CASE: case DEFAULT: case EOF: + return List.nil(); + case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: + case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: + case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: + return List.of(parseStatement()); + case MONKEYS_AT: + case FINAL: { + String dc = token.comment(CommentStyle.JAVADOC); + JCModifiers mods = modifiersOpt(); + if (token.kind == INTERFACE || + token.kind == CLASS || + allowEnums && token.kind == ENUM) { + return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); + } else { + JCExpression t = parseType(); + ListBuffer<JCStatement> stats = + variableDeclarators(mods, t, new ListBuffer<JCStatement>()); + // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon + storeEnd(stats.elems.last(), token.endPos); + accept(SEMI); + return stats.toList(); } - - // error recovery - if (token.pos == lastErrPos) + } + case ABSTRACT: case STRICTFP: { + String dc = token.comment(CommentStyle.JAVADOC); + JCModifiers mods = modifiersOpt(); + return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); + } + case INTERFACE: + case CLASS: + String dc = token.comment(CommentStyle.JAVADOC); + return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); + case ENUM: + case ASSERT: + if (allowEnums && token.kind == ENUM) { + error(token.pos, "local.enum"); + dc = token.comment(CommentStyle.JAVADOC); + return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); + } else if (allowAsserts && token.kind == ASSERT) { + return List.of(parseStatement()); + } + /* fall through to default */ + default: + Token prevToken = token; + JCExpression t = term(EXPR | TYPE); + if (token.kind == COLON && t.hasTag(IDENT)) { + nextToken(); + JCStatement stat = parseStatement(); + return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat)); + } else if ((lastmode & TYPE) != 0 && + (token.kind == IDENTIFIER || + token.kind == ASSERT || + token.kind == ENUM)) { + pos = token.pos; + JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); + F.at(pos); + ListBuffer<JCStatement> stats = + variableDeclarators(mods, t, new ListBuffer<JCStatement>()); + // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon + storeEnd(stats.elems.last(), token.endPos); + accept(SEMI); return stats.toList(); - if (token.pos <= endPosTable.errorEndPos) { - skip(false, true, true, true); - lastErrPos = token.pos; + } else { + // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon + JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t))); + accept(SEMI); + return List.<JCStatement>of(expr); } } } @@ -1917,11 +1951,11 @@ case IF: { nextToken(); JCExpression cond = parExpression(); - JCStatement thenpart = parseStatement(); + JCStatement thenpart = parseStatementAsBlock(); JCStatement elsepart = null; if (token.kind == ELSE) { nextToken(); - elsepart = parseStatement(); + elsepart = parseStatementAsBlock(); } return F.at(pos).If(cond, thenpart, elsepart); } @@ -1938,7 +1972,7 @@ accept(COLON); JCExpression expr = parseExpression(); accept(RPAREN); - JCStatement body = parseStatement(); + JCStatement body = parseStatementAsBlock(); return F.at(pos).ForeachLoop(var, expr, body); } else { accept(SEMI); @@ -1946,19 +1980,19 @@ accept(SEMI); List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); accept(RPAREN); - JCStatement body = parseStatement(); + JCStatement body = parseStatementAsBlock(); return F.at(pos).ForLoop(inits, cond, steps, body); } } case WHILE: { nextToken(); JCExpression cond = parExpression(); - JCStatement body = parseStatement(); + JCStatement body = parseStatementAsBlock(); return F.at(pos).WhileLoop(cond, body); } case DO: { nextToken(); - JCStatement body = parseStatement(); + JCStatement body = parseStatementAsBlock(); accept(WHILE); JCExpression cond = parExpression(); JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Apr 09 21:58:05 2012 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Apr 10 23:19:26 2012 -0700 @@ -196,6 +196,9 @@ compiler.err.clash.with.pkg.of.same.name=\ {0} {1} clashes with package of same name +compiler.err.class.not.allowed=\ + class, interface or enum declaration not allowed here + compiler.err.const.expr.req=\ constant expression required @@ -385,6 +388,9 @@ compiler.err.illegal.start.of.expr=\ illegal start of expression +compiler.err.illegal.start.of.stmt=\ + illegal start of statement + compiler.err.illegal.start.of.type=\ illegal start of type @@ -446,6 +452,9 @@ compiler.err.varargs.and.old.array.syntax=\ legacy array notation not allowed on variable-arity parameter +compiler.err.variable.not.allowed=\ + variable declaration not allowed here + # 0: name compiler.err.label.already.in.use=\ label {0} already in use
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/ClassVersionChecker.java Tue Apr 10 23:19:26 2012 -0700 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2012, 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 7157626 + * @summary Test major version for all legal combinations for -source and -target + * @author sgoel + * + */ + +import java.io.*; +import java.nio.*; +import java.util.*; +import java.util.regex.*; + +public class ClassVersionChecker { + + int errors; + String[] jdk = {"","1.2","1.3","1.4","1.5","1.6","1.7","1.8"}; + File javaFile = null; + + public static void main(String[] args) throws Throwable { + new ClassVersionChecker().run(); + } + + void run() throws Exception { + writeTestFile(); + /* Rules applicable for -source and -target combinations + * 1. If both empty, version num is for 1.7 + * 2. If source is not empty and target is empty, version is based on source + * 3. If both non-empty, version is based on target + */ + + /* -source (0=>empty,1=>1.2,...) X -target (0=>empty,1=>1.2,...) + * ver[0][0] => no -source or -target was given + * -1 => invalid combinations + */ + int[][] ver = + {{51, -1, -1, -1, -1, -1, -1, -1}, + {48, 46, 47, 48, 49, 50, 51, 51}, + {48, 46, 47, 48, 49, 50, 51, 51}, + {48, -1, -1, 48, 49, 50, 51, 51}, + {51, -1, -1, -1, 49, 50, 51, 51}, + {51, -1, -1, -1, -1, 50, 51, 51}, + {51, -1, -1, -1, -1, -1, 51, 51}, + {51, -1, -1, -1, -1, -1, -1, 51}}; + + // Loop to run all possible combinations of source/target values + for (int i = 0; i< ver.length; i++) { + for (int j = 0 ; j< ver[i].length; j++) { + if(ver[i][j] != -1) { + logMsg("Index values for i = " + i + " j = " + j); + logMsg("Running for src = " + jdk[i] + " target = "+jdk[j] +" expected = " + ver[i][j]); + test(i,j, ver[i][j]); + } + } + } + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void test (int i, int j, int expected) { + File classFile = compileTestFile(i, j, javaFile); + short majorVer = getMajorVersion(classFile); + checkVersion(majorVer, expected); + } + + void writeTestFile() throws IOException { + javaFile = new File("Test.java"); + try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(javaFile)));) { + out.println("class Test { "); + out.println(" public void foo() { }"); + out.println("}"); + } catch (IOException ioe) { + error("IOException while creating Test.java" + ioe); + } + } + + File compileTestFile(int i , int j, File f) { + int rc = -1; + // Src and target are empty + if (i == 0 && j == 0 ) { + rc = compile("-g", f.getPath()); + } else if( j == 0 ) { // target is empty + rc = compile("-source", jdk[i], "-g", f.getPath()); + } else { + rc = compile("-source", jdk[i], "-target", jdk[j], "-g", f.getPath()); + } + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + int compile(String... args) { + return com.sun.tools.javac.Main.compile(args); + } + + void logMsg (String str) { + System.out.println(str); + } + + short getMajorVersion(File f) { + List<String> args = new ArrayList<String>(); + short majorVer = 0; + try(DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));) { + in.readInt(); + in.readShort(); + majorVer = in.readShort(); + System.out.println("major version:" + majorVer); + } catch (IOException e) { + error("IOException while reading Test.class" + e); + } + return majorVer; + } + + void checkVersion(short majorVer, int expected) { + if (majorVer != expected ) { + error("versions did not match, Expected: " + expected + "Got: " + majorVer); + } + } + + void error(String msg) { + System.out.println("error: " + msg); + errors++; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/IllegalStartOfStmt.java Tue Apr 10 23:19:26 2012 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012, 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.illegal.start.of.stmt +// key: compiler.err.expected3 + +class IllegalStartOfStmt { + void m() { + if (true) } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/NotAllowedClass.java Tue Apr 10 23:19:26 2012 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012, 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.class.not.allowed + +class NotAllowedClass { + void t1() { + if (true) + class X {} + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/NotAllowedVariable.java Tue Apr 10 23:19:26 2012 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012, 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.variable.not.allowed + +class NotAllowedVariable { + void t1() { + if (true) + int x = 0; + } +}
--- a/test/tools/javac/parser/JavacParserTest.java Mon Apr 09 21:58:05 2012 -0700 +++ b/test/tools/javac/parser/JavacParserTest.java Tue Apr 10 23:19:26 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, 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 @@ -596,8 +596,8 @@ public void testVariableInIfThen3() throws IOException { String code = "package t; class Test { "+ - "private static void t(String name) { " + - "if (name != null) abstract } }"; + "private static void t() { " + + "if (true) abstract class F {} }}"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, @@ -612,7 +612,51 @@ } assertEquals("testVariableInIfThen3", - Arrays.<String>asList("compiler.err.illegal.start.of.expr"), + Arrays.<String>asList("compiler.err.class.not.allowed"), codes); + } + + public void testVariableInIfThen4() throws IOException { + + String code = "package t; class Test { "+ + "private static void t(String name) { " + + "if (name != null) interface X {} } }"; + DiagnosticCollector<JavaFileObject> coll = + new DiagnosticCollector<JavaFileObject>(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List<String> codes = new LinkedList<String>(); + + for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen4", + Arrays.<String>asList("compiler.err.class.not.allowed"), codes); + } + + public void testVariableInIfThen5() throws IOException { + + String code = "package t; class Test { "+ + "private static void t() { " + + "if (true) } }"; + DiagnosticCollector<JavaFileObject> coll = + new DiagnosticCollector<JavaFileObject>(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List<String> codes = new LinkedList<String>(); + + for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen5", + Arrays.<String>asList("compiler.err.illegal.start.of.stmt"), codes); } @@ -808,8 +852,6 @@ testPositionBrokenSource126732b(); // Fails, these tests yet to be addressed - testVariableInIfThen1(); - testVariableInIfThen2(); testPositionForEnumModifiers(); testStartPositionEnumConstantInit(); } @@ -821,7 +863,11 @@ testPreferredPositionForBinaryOp(); testStartPositionForMethodWithoutModifiers(); testVarPos(); + testVariableInIfThen1(); + testVariableInIfThen2(); testVariableInIfThen3(); + testVariableInIfThen4(); + testVariableInIfThen5(); testMissingExponent(); testTryResourcePos(); testOperatorMissingError();