Ticket #7137: Properly detect C++14 digit separators. (#802)

Add an optional extended description…
This commit is contained in:
Simon Martin 2016-06-04 22:55:55 +02:00 committed by PKEuS
parent 3916cd628e
commit 3095f47a7b
5 changed files with 67 additions and 1 deletions

View File

@ -1249,6 +1249,42 @@ bool MathLib::isOctalDigit(char c)
return (c >= '0' && c <= '7');
}
bool MathLib::isDigitSeparator(const std::string& iCode, std::string::size_type iPos) {
if (iPos == 0 || iPos >= iCode.size() || iCode[iPos] != '\'')
return false;
std::string::size_type i = iPos - 1;
while (std::isxdigit(iCode[i])) {
if (i == 0)
return true; // Only xdigits before '
--i;
}
if (i == iPos - 1) { // No xdigit before '
return false;
} else {
switch(iCode[i]) {
case ' ':
case '.':
case ',':
case 'x':
case '(':
case '{':
case '+':
case '-':
case '*':
case '%':
case '/':
case '&':
case '|':
case '^':
case '~':
case '=':
return true;
default:
return false;
}
}
}
MathLib::value operator+(const MathLib::value &v1, const MathLib::value &v2)
{
return MathLib::value::calc('+',v1,v2);

View File

@ -122,6 +122,13 @@ public:
* */
static MathLib::bigint characterLiteralToLongNumber(const std::string& str);
/**
* \param iCode Code being considered
* \param iPos A posision within iCode
* \return Whether iCode[iPos] is a C++14 digit separator
*/
static bool isDigitSeparator(const std::string& iCode, std::string::size_type iPos);
private:
/*
* \param iLiteral A character literal

View File

@ -697,7 +697,7 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
}
// C++14 digit separators
if (ch == '\'' && std::isxdigit(previous))
if (MathLib::isDigitSeparator(str, i))
; // Just skip it.
// String or char constants..

View File

@ -59,6 +59,7 @@ private:
TEST_CASE(abs);
TEST_CASE(toString);
TEST_CASE(characterLiteralsNormalization);
TEST_CASE(CPP14DigitSeparators);
}
void isGreater() const {
@ -1143,6 +1144,23 @@ private:
// Unsupported single escape sequence
ASSERT_THROW(MathLib::normalizeCharacterLiteral("\\c"), InternalError);
}
void CPP14DigitSeparators() { // Ticket #7137
ASSERT(MathLib::isDigitSeparator("'", 0) == false);
ASSERT(MathLib::isDigitSeparator("123'0;", 3));
ASSERT(MathLib::isDigitSeparator("foo(1'2);", 5));
ASSERT(MathLib::isDigitSeparator("foo(1,1'2);", 7));
ASSERT(MathLib::isDigitSeparator("int a=1'234-1'2-'0';", 7));
ASSERT(MathLib::isDigitSeparator("int a=1'234-1'2-'0';", 13));
ASSERT(MathLib::isDigitSeparator("int a=1'234-1'2-'0';", 16) == false);
ASSERT(MathLib::isDigitSeparator("int b=1+9'8;", 9));
ASSERT(MathLib::isDigitSeparator("if (1'2) { char c = 'c'; }", 5));
ASSERT(MathLib::isDigitSeparator("if (120%1'2) { char c = 'c'; }", 9));
ASSERT(MathLib::isDigitSeparator("if (120&1'2) { char c = 'c'; }", 9));
ASSERT(MathLib::isDigitSeparator("if (120|1'2) { char c = 'c'; }", 9));
ASSERT(MathLib::isDigitSeparator("if (120%1'2) { char c = 'c'; }", 24) == false);
ASSERT(MathLib::isDigitSeparator("if (120%1'2) { char c = 'c'; }", 26) == false);
}
};
REGISTER_TEST(TestMathLib)

View File

@ -352,6 +352,11 @@ private:
ASSERT_EQUALS("int i = 0x0F0FFFFF;", preprocessorRead("int i = 0x0F0F'FFFF;"));
ASSERT_EQUALS("", errout.str());
// Ticket #7137
const char code[] = "void t(char c) { switch (c) { case'M': break; } }";
ASSERT_EQUALS(code, preprocessorRead(code));
ASSERT_EQUALS("", errout.str());
}