Description
Solidity rejects an underscore placed directly against the exponent marker of a decimal number literal, but only when the exponent marker is lowercase e. The post-lex validator in libsolidity/analysis/SyntaxChecker.cpp:342-346 searches the literal text for the fixed lowercase substrings "e_" and "_e":
// libsolidity/analysis/SyntaxChecker.cpp:342-346 (inside visit(Literal), decimal branch)
if (value.find("_e") != ASTString::npos)
m_errorReporter.syntaxError(6415_error, _literal.location(),
"Invalid use of underscores in number literal. No underscore at the end of the mantissa allowed.");
if (value.find("e_") != ASTString::npos)
m_errorReporter.syntaxError(6165_error, _literal.location(),
"Invalid use of underscores in number literal. No underscore in front of exponent allowed.");
The scanner equally accepts uppercase E as an exponent marker (liblangutil/Scanner.cpp:996, m_char == 'e' || m_char == 'E'), and the AST keeps the literal's original case, so "1E_5" contains "E_" and never matches "e_" — find returns npos and no error is emitted. As a result, every uppercase-E malformed literal slips through: 1E_5 and 1_E5 are silently accepted as 100000 (underscore dropped), while the byte-identical lowercase 1e_5/1_e5 are hard compile errors 6165/6415.
Expected: the underscore-placement check should be case-insensitive so that 1E_5/1_E5 are rejected with the same errors (6165/6415) as their lowercase equivalents, instead of silently accepting a malformed literal with no diagnostic.
Environment
- Compiler version:
47b9dedda
Steps to Reproduce
The following compiles without any diagnostic; the underscores are silently dropped:
uint constant A = 1E_5; // accepted, == 100000 (lowercase 1e_5 => Error 6165)
uint constant B = 1_E5; // accepted, == 100000 (lowercase 1_e5 => Error 6415)
uint constant C = 3E_0; // accepted, == 3
For comparison, the byte-identical lowercase forms 1e_5 and 1_e5 are hard errors (6165 and 6415 respectively), demonstrating the case-sensitivity asymmetry.
Description
Solidity rejects an underscore placed directly against the exponent marker of a decimal number literal, but only when the exponent marker is lowercase
e. The post-lex validator inlibsolidity/analysis/SyntaxChecker.cpp:342-346searches the literal text for the fixed lowercase substrings"e_"and"_e":The scanner equally accepts uppercase
Eas an exponent marker (liblangutil/Scanner.cpp:996,m_char == 'e' || m_char == 'E'), and the AST keeps the literal's original case, so"1E_5"contains"E_"and never matches"e_"—findreturnsnposand no error is emitted. As a result, every uppercase-Emalformed literal slips through:1E_5and1_E5are silently accepted as100000(underscore dropped), while the byte-identical lowercase1e_5/1_e5are hard compile errors 6165/6415.Expected: the underscore-placement check should be case-insensitive so that
1E_5/1_E5are rejected with the same errors (6165/6415) as their lowercase equivalents, instead of silently accepting a malformed literal with no diagnostic.Environment
47b9deddaSteps to Reproduce
The following compiles without any diagnostic; the underscores are silently dropped:
For comparison, the byte-identical lowercase forms
1e_5and1_e5are hard errors (6165 and 6415 respectively), demonstrating the case-sensitivity asymmetry.