Support integer Z suffix and user defined literals with _ suffix (#10807, #11438) (#5130)

Co-authored-by: Carl Morgan <no-reply@crown.com>
This commit is contained in:
Carl Morgan 2023-06-09 06:03:41 +12:00 committed by GitHub
parent d4902109cd
commit 6741f774b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 8 deletions

View File

@ -546,7 +546,7 @@ bool MathLib::isDecimalFloat(const std::string &str)
if (str.empty()) if (str.empty())
return false; return false;
enum class State { enum class State {
START, BASE_DIGITS1, LEADING_DECIMAL, TRAILING_DECIMAL, BASE_DIGITS2, E, MANTISSA_PLUSMINUS, MANTISSA_DIGITS, SUFFIX_F, SUFFIX_L START, BASE_DIGITS1, LEADING_DECIMAL, TRAILING_DECIMAL, BASE_DIGITS2, E, MANTISSA_PLUSMINUS, MANTISSA_DIGITS, SUFFIX_F, SUFFIX_L, SUFFIX_LITERAL_LEADER, SUFFIX_LITERAL
} state = State::START; } state = State::START;
std::string::const_iterator it = str.cbegin(); std::string::const_iterator it = str.cbegin();
if ('+' == *it || '-' == *it) if ('+' == *it || '-' == *it)
@ -582,6 +582,8 @@ bool MathLib::isDecimalFloat(const std::string &str)
state = State::SUFFIX_F; state = State::SUFFIX_F;
else if (*it=='l' || *it=='L') else if (*it=='l' || *it=='L')
state = State::SUFFIX_L; state = State::SUFFIX_L;
else if (*it == '_')
state = State::SUFFIX_LITERAL_LEADER;
else if (std::isdigit(static_cast<unsigned char>(*it))) else if (std::isdigit(static_cast<unsigned char>(*it)))
state = State::BASE_DIGITS2; state = State::BASE_DIGITS2;
else else
@ -594,6 +596,8 @@ bool MathLib::isDecimalFloat(const std::string &str)
state = State::SUFFIX_F; state = State::SUFFIX_F;
else if (*it=='l' || *it=='L') else if (*it=='l' || *it=='L')
state = State::SUFFIX_L; state = State::SUFFIX_L;
else if (*it == '_')
state = State::SUFFIX_LITERAL_LEADER;
else if (!std::isdigit(static_cast<unsigned char>(*it))) else if (!std::isdigit(static_cast<unsigned char>(*it)))
return false; return false;
break; break;
@ -619,13 +623,18 @@ bool MathLib::isDecimalFloat(const std::string &str)
else if (!std::isdigit(static_cast<unsigned char>(*it))) else if (!std::isdigit(static_cast<unsigned char>(*it)))
return false; return false;
break; break;
// Ensure at least one post _ char for user defined literals
case State::SUFFIX_LITERAL:
case State::SUFFIX_LITERAL_LEADER:
state = State::SUFFIX_LITERAL;
break;
case State::SUFFIX_F: case State::SUFFIX_F:
return false; return false;
case State::SUFFIX_L: case State::SUFFIX_L:
return false; return false;
} }
} }
return (state==State::BASE_DIGITS2 || state==State::MANTISSA_DIGITS || state==State::TRAILING_DECIMAL || state==State::SUFFIX_F || state==State::SUFFIX_L); return (state==State::BASE_DIGITS2 || state==State::MANTISSA_DIGITS || state==State::TRAILING_DECIMAL || state==State::SUFFIX_F || state==State::SUFFIX_L || (state==State::SUFFIX_LITERAL));
} }
bool MathLib::isNegative(const std::string &str) bool MathLib::isNegative(const std::string &str)
@ -644,7 +653,7 @@ bool MathLib::isPositive(const std::string &str)
static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::const_iterator end, bool supportMicrosoftExtensions=true) static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::const_iterator end, bool supportMicrosoftExtensions=true)
{ {
enum class Status { START, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU, SUFFIX_I, SUFFIX_I6, SUFFIX_I64, SUFFIX_UI, SUFFIX_UI6, SUFFIX_UI64 } state = Status::START; enum class Status { START, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_UZ, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU, SUFFIX_I, SUFFIX_I6, SUFFIX_I64, SUFFIX_UI, SUFFIX_UI6, SUFFIX_UI64, SUFFIX_Z, SUFFIX_LITERAL_LEADER, SUFFIX_LITERAL } state = Status::START;
for (; it != end; ++it) { for (; it != end; ++it) {
switch (state) { switch (state) {
case Status::START: case Status::START:
@ -652,14 +661,20 @@ static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::
state = Status::SUFFIX_U; state = Status::SUFFIX_U;
else if (*it == 'l' || *it == 'L') else if (*it == 'l' || *it == 'L')
state = Status::SUFFIX_L; state = Status::SUFFIX_L;
else if (*it == 'z' || *it == 'Z')
state = Status::SUFFIX_Z;
else if (supportMicrosoftExtensions && (*it == 'i' || *it == 'I')) else if (supportMicrosoftExtensions && (*it == 'i' || *it == 'I'))
state = Status::SUFFIX_I; state = Status::SUFFIX_I;
else if (*it == '_')
state = Status::SUFFIX_LITERAL_LEADER;
else else
return false; return false;
break; break;
case Status::SUFFIX_U: case Status::SUFFIX_U:
if (*it == 'l' || *it == 'L') if (*it == 'l' || *it == 'L')
state = Status::SUFFIX_UL; // UL state = Status::SUFFIX_UL; // UL
else if (*it == 'z' || *it == 'Z')
state = Status::SUFFIX_UZ; // UZ
else if (supportMicrosoftExtensions && (*it == 'i' || *it == 'I')) else if (supportMicrosoftExtensions && (*it == 'i' || *it == 'I'))
state = Status::SUFFIX_UI; state = Status::SUFFIX_UI;
else else
@ -711,19 +726,33 @@ static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::
else else
return false; return false;
break; break;
case Status::SUFFIX_Z:
if (*it == 'u' || *it == 'U')
state = Status::SUFFIX_UZ;
else
return false;
break;
// Ensure at least one post _ char for user defined literals
case Status::SUFFIX_LITERAL:
case Status::SUFFIX_LITERAL_LEADER:
state = Status::SUFFIX_LITERAL;
break;
default: default:
return false; return false;
} }
} }
return ((state == Status::SUFFIX_U) || return ((state == Status::SUFFIX_U) ||
(state == Status::SUFFIX_L) || (state == Status::SUFFIX_L) ||
(state == Status::SUFFIX_Z) ||
(state == Status::SUFFIX_UL) || (state == Status::SUFFIX_UL) ||
(state == Status::SUFFIX_UZ) ||
(state == Status::SUFFIX_LU) || (state == Status::SUFFIX_LU) ||
(state == Status::SUFFIX_LL) || (state == Status::SUFFIX_LL) ||
(state == Status::SUFFIX_ULL) || (state == Status::SUFFIX_ULL) ||
(state == Status::SUFFIX_LLU) || (state == Status::SUFFIX_LLU) ||
(state == Status::SUFFIX_I64) || (state == Status::SUFFIX_I64) ||
(state == Status::SUFFIX_UI64)); (state == Status::SUFFIX_UI64) ||
(state == Status::SUFFIX_LITERAL));
} }
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction

View File

@ -960,6 +960,14 @@ private:
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0ULL")); ASSERT_EQUALS(true, MathLib::isIntHex("-0x0ULL"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0LLU")); ASSERT_EQUALS(true, MathLib::isIntHex("+0x0LLU"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0LLU")); ASSERT_EQUALS(true, MathLib::isIntHex("-0x0LLU"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0Z"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0Z"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0ZU"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0ZU"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0UZ"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0UZ"));
ASSERT_EQUALS(true, MathLib::isIntHex("+0x0Uz"));
ASSERT_EQUALS(true, MathLib::isIntHex("-0x0Uz"));
// negative testing // negative testing
ASSERT_EQUALS(false, MathLib::isIntHex("+0x")); ASSERT_EQUALS(false, MathLib::isIntHex("+0x"));
@ -972,10 +980,6 @@ private:
ASSERT_EQUALS(false, MathLib::isIntHex(" ")); ASSERT_EQUALS(false, MathLib::isIntHex(" "));
ASSERT_EQUALS(false, MathLib::isIntHex(" ")); ASSERT_EQUALS(false, MathLib::isIntHex(" "));
ASSERT_EQUALS(false, MathLib::isIntHex("0")); ASSERT_EQUALS(false, MathLib::isIntHex("0"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Z"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Z"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Uz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Uz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Lz")); ASSERT_EQUALS(false, MathLib::isIntHex("+0x0Lz"));
ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Lz")); ASSERT_EQUALS(false, MathLib::isIntHex("-0x0Lz"));
ASSERT_EQUALS(false, MathLib::isIntHex("+0x0LUz")); ASSERT_EQUALS(false, MathLib::isIntHex("+0x0LUz"));
@ -1018,12 +1022,19 @@ private:
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("u")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("u"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ul")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ul"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ull")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ull"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("uz"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("l")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("l"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("lu")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("lu"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ll")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ll"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("llu")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("llu"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("llU")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("llU"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("LLU")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("LLU"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("z"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("Z"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("zu"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("UZ"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("ZU"));
// Microsoft extensions: // Microsoft extensions:
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("i64")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("i64"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("I64")); ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("I64"));
@ -1033,6 +1044,10 @@ private:
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("I64", false)); ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("I64", false));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("ui64", false)); ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("ui64", false));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("UI64", false)); ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("UI64", false));
// User defined suffix literals
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("_"));
ASSERT_EQUALS(true, MathLib::isValidIntegerSuffix("_MyUserDefinedLiteral"));
} }
void ispositive() const { void ispositive() const {
@ -1057,6 +1072,13 @@ private:
ASSERT_EQUALS(true, MathLib::isFloat("0.f")); ASSERT_EQUALS(true, MathLib::isFloat("0.f"));
ASSERT_EQUALS(true, MathLib::isFloat("0.f")); ASSERT_EQUALS(true, MathLib::isFloat("0.f"));
ASSERT_EQUALS(true, MathLib::isFloat("0xA.Fp-10")); ASSERT_EQUALS(true, MathLib::isFloat("0xA.Fp-10"));
// User defined suffix literals
ASSERT_EQUALS(false, MathLib::isFloat("0_"));
ASSERT_EQUALS(false, MathLib::isFloat("0._"));
ASSERT_EQUALS(false, MathLib::isFloat("0.1_"));
ASSERT_EQUALS(true, MathLib::isFloat("0.0_MyUserDefinedLiteral"));
ASSERT_EQUALS(true, MathLib::isFloat("0._MyUserDefinedLiteral"));
} }
void isDecimalFloat() const { void isDecimalFloat() const {
@ -1164,6 +1186,13 @@ private:
ASSERT_EQUALS(true, MathLib::isDecimalFloat("1.0E+1")); ASSERT_EQUALS(true, MathLib::isDecimalFloat("1.0E+1"));
ASSERT_EQUALS(true, MathLib::isDecimalFloat("1.0E-1")); ASSERT_EQUALS(true, MathLib::isDecimalFloat("1.0E-1"));
ASSERT_EQUALS(true, MathLib::isDecimalFloat("-1.0E+1")); ASSERT_EQUALS(true, MathLib::isDecimalFloat("-1.0E+1"));
// User defined suffix literals
ASSERT_EQUALS(false, MathLib::isDecimalFloat("0_"));
ASSERT_EQUALS(false, MathLib::isDecimalFloat(".1_"));
ASSERT_EQUALS(false, MathLib::isDecimalFloat("0.1_"));
ASSERT_EQUALS(true, MathLib::isDecimalFloat("0.0_MyUserDefinedLiteral"));
ASSERT_EQUALS(true, MathLib::isDecimalFloat(".1_MyUserDefinedLiteral"));
} }
void naninf() const { void naninf() const {
@ -1198,6 +1227,14 @@ private:
ASSERT_EQUALS(false, MathLib::isDec("+x")); ASSERT_EQUALS(false, MathLib::isDec("+x"));
ASSERT_EQUALS(false, MathLib::isDec("x")); ASSERT_EQUALS(false, MathLib::isDec("x"));
ASSERT_EQUALS(false, MathLib::isDec("")); ASSERT_EQUALS(false, MathLib::isDec(""));
// User defined suffix literals
ASSERT_EQUALS(false, MathLib::isDec("0_"));
ASSERT_EQUALS(false, MathLib::isDec("+0_"));
ASSERT_EQUALS(false, MathLib::isDec("-1_"));
ASSERT_EQUALS(true, MathLib::isDec("0_MyUserDefinedLiteral"));
ASSERT_EQUALS(true, MathLib::isDec("+1_MyUserDefinedLiteral"));
ASSERT_EQUALS(true, MathLib::isDec("-1_MyUserDefinedLiteral"));
} }
void isNullValue() const { void isNullValue() const {