8325440: Confusing error reported for octal literals with wrong digits
Reviewed-by: vromero
This commit is contained in:
parent
5daf622aea
commit
8b70b8d85a
src/jdk.compiler/share/classes/com/sun/tools/javac
test/langtools/tools/javac
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2024, 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
|
||||
@ -742,8 +742,9 @@ public class JavaTokenizer extends UnicodeReader {
|
||||
private void scanNumber(int pos, int radix) {
|
||||
// for octal, allow base-10 digit in case it's a float literal
|
||||
this.radix = radix;
|
||||
int digitRadix = (radix == 8 ? 10 : radix);
|
||||
int firstDigit = digit(pos, Math.max(10, digitRadix));
|
||||
boolean permitFloatingPoint = radix == 8 || radix == 10;
|
||||
int digitRadix = Math.max(10, radix);
|
||||
int firstDigit = digit(pos, digitRadix);
|
||||
boolean seendigit = firstDigit >= 0;
|
||||
boolean seenValidDigit = firstDigit >= 0 && firstDigit < digitRadix;
|
||||
|
||||
@ -755,10 +756,10 @@ public class JavaTokenizer extends UnicodeReader {
|
||||
scanHexFractionAndSuffix(pos, seendigit);
|
||||
} else if (seendigit && radix == 16 && isOneOf('p', 'P')) {
|
||||
scanHexExponentAndSuffix(pos);
|
||||
} else if (digitRadix == 10 && is('.')) {
|
||||
} else if (permitFloatingPoint && is('.')) {
|
||||
putThenNext();
|
||||
scanFractionAndSuffix(pos);
|
||||
} else if (digitRadix == 10 && isOneOf('e', 'E', 'f', 'F', 'd', 'D')) {
|
||||
} else if (permitFloatingPoint && isOneOf('e', 'E', 'f', 'F', 'd', 'D')) {
|
||||
scanFractionAndSuffix(pos);
|
||||
} else {
|
||||
if (!seenValidDigit) {
|
||||
@ -771,13 +772,6 @@ public class JavaTokenizer extends UnicodeReader {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If it is not a floating point literal,
|
||||
// the octal number should be rescanned correctly.
|
||||
if (radix == 8) {
|
||||
sb.setLength(0);
|
||||
reset(pos);
|
||||
scanDigits(pos, 8);
|
||||
}
|
||||
|
||||
if (acceptOneOf('l', 'L')) {
|
||||
tk = TokenKind.LONGLITERAL;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2024, 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
|
||||
@ -770,7 +770,7 @@ public class JavacParser implements Parser {
|
||||
TypeTag.INT,
|
||||
Convert.string2int(strval(prefix), token.radix()));
|
||||
} catch (NumberFormatException ex) {
|
||||
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
|
||||
reportIntegralLiteralError(prefix, pos);
|
||||
}
|
||||
break;
|
||||
case LONGLITERAL:
|
||||
@ -779,7 +779,7 @@ public class JavacParser implements Parser {
|
||||
TypeTag.LONG,
|
||||
Long.valueOf(Convert.string2long(strval(prefix), token.radix())));
|
||||
} catch (NumberFormatException ex) {
|
||||
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
|
||||
reportIntegralLiteralError(prefix, pos);
|
||||
}
|
||||
break;
|
||||
case FLOATLITERAL: {
|
||||
@ -862,6 +862,28 @@ public class JavacParser implements Parser {
|
||||
String s = token.stringVal();
|
||||
return prefix.isEmpty() ? s : prefix + s;
|
||||
}
|
||||
void reportIntegralLiteralError(Name prefix, int pos) {
|
||||
int radix = token.radix();
|
||||
if (radix == 2 || radix == 8) {
|
||||
//attempt to produce more user-friendly error message for
|
||||
//binary and octal literals with wrong digits:
|
||||
String value = strval(prefix);
|
||||
char[] cs = value.toCharArray();
|
||||
for (int i = 0; i < cs.length; i++) {
|
||||
char c = cs[i];
|
||||
int d = Character.digit(c, radix);
|
||||
if (d == (-1)) {
|
||||
Error err = radix == 2 ? Errors.IllegalDigitInBinaryLiteral
|
||||
: Errors.IllegalDigitInOctalLiteral;
|
||||
log.error(DiagnosticFlag.SYNTAX,
|
||||
token.pos + i,
|
||||
err);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
|
||||
}
|
||||
|
||||
/** terms can be either expressions or types.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1999, 2024, 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
|
||||
@ -740,6 +740,12 @@ compiler.err.illegal.underscore=\
|
||||
compiler.err.illegal.dot=\
|
||||
illegal ''.''
|
||||
|
||||
compiler.err.illegal.digit.in.binary.literal=\
|
||||
illegal digit in a binary literal
|
||||
|
||||
compiler.err.illegal.digit.in.octal.literal=\
|
||||
illegal digit in an octal literal
|
||||
|
||||
# 0: symbol
|
||||
compiler.err.illegal.qual.not.icls=\
|
||||
illegal qualifier; {0} is not an inner class
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.digit.in.binary.literal
|
||||
|
||||
class IllegalDigitInOctalLiteral {
|
||||
int i = 0b8;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.digit.in.octal.literal
|
||||
|
||||
class IllegalDigitInOctalLiteral {
|
||||
int i = 08;
|
||||
}
|
@ -24,5 +24,5 @@
|
||||
// key: compiler.err.invalid.binary.number
|
||||
|
||||
class InvalidBinaryNumber {
|
||||
int i = 0b201000010;
|
||||
int i = 0b;
|
||||
}
|
||||
|
@ -83,7 +83,6 @@ public class JavaLexerTest {
|
||||
|
||||
static final TestTuple[] FAILING_TESTS = {
|
||||
new TestTuple(LONGLITERAL, "0bL"),
|
||||
new TestTuple(LONGLITERAL, "0b20L"),
|
||||
new TestTuple(LONGLITERAL, "0xL"),
|
||||
new TestTuple(INTLITERAL, "0xG000L", "0x"),
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2024, 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,8 +23,8 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8267361
|
||||
* @summary JavaTokenizer reads octal numbers mistakenly
|
||||
* @bug 8267361 8325440
|
||||
* @summary Verify meaniningfull errors for broken octal literals.
|
||||
* @library /tools/lib
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -62,6 +62,9 @@ public class OctalNumberTest extends TestRunner {
|
||||
int c = 02389;
|
||||
int d = 028a;
|
||||
int e = 02a8;
|
||||
int f = 0b;
|
||||
int g = 0b2;
|
||||
int h = 0b12;
|
||||
}""";
|
||||
List<String> output = new JavacTask(tb)
|
||||
.sources(code)
|
||||
@ -70,13 +73,17 @@ public class OctalNumberTest extends TestRunner {
|
||||
.writeAll()
|
||||
.getOutputLines(Task.OutputKind.DIRECT);
|
||||
List<String> expected = Arrays.asList(
|
||||
"Digit.java:3:14: compiler.err.expected: ';'",
|
||||
"Digit.java:4:16: compiler.err.expected: ';'",
|
||||
"Digit.java:5:15: compiler.err.expected: ';'",
|
||||
"Digit.java:3:14: compiler.err.illegal.digit.in.octal.literal",
|
||||
"Digit.java:4:16: compiler.err.illegal.digit.in.octal.literal",
|
||||
"Digit.java:5:15: compiler.err.illegal.digit.in.octal.literal",
|
||||
"Digit.java:5:16: compiler.err.expected: ';'",
|
||||
"Digit.java:5:17: compiler.err.expected: token.identifier",
|
||||
"Digit.java:6:15: compiler.err.expected: ';'",
|
||||
"Digit.java:6:17: compiler.err.expected: token.identifier",
|
||||
"6 errors");
|
||||
"Digit.java:7:13: compiler.err.invalid.binary.number",
|
||||
"Digit.java:8:13: compiler.err.illegal.digit.in.binary.literal",
|
||||
"Digit.java:9:14: compiler.err.illegal.digit.in.binary.literal",
|
||||
"10 errors");
|
||||
tb.checkEqual(expected, output);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
BadBinaryLiterals.java:10:24: compiler.err.expected: ';'
|
||||
BadBinaryLiterals.java:10:22: compiler.err.illegal.digit.in.binary.literal
|
||||
BadBinaryLiterals.java:12:21: compiler.err.int.number.too.large: 111111111111111111111111111111111
|
||||
BadBinaryLiterals.java:14:21: compiler.err.int.number.too.large: 11111111111111111111111111111111111111111111111111111111111111111
|
||||
BadBinaryLiterals.java:15:27: compiler.err.expected: ';'
|
||||
|
Loading…
x
Reference in New Issue
Block a user