Fixed #4481 (Simplify %str% [ %num% ])

This commit is contained in:
Erik Lax 2013-01-13 20:52:38 +01:00 committed by Daniel Marjamäki
parent f0ce26a2aa
commit 723d95597b
5 changed files with 70 additions and 0 deletions

View File

@ -741,6 +741,34 @@ std::size_t Token::getStrLength(const Token *tok)
return len;
}
std::string Token::getCharAt(const Token *tok, std::size_t index)
{
assert(tok != NULL);
const std::string strValue(tok->strValue());
const char *str = strValue.c_str();
while (*str) {
if (index == 0) {
std::string ret;
if (*str == '\\') {
ret = *str;
++str;
}
ret += *str;
return ret;
}
if (*str == '\\')
++str;
++str;
--index;
}
assert(index == 0);
return "\\0";
}
void Token::move(Token *srcStart, Token *srcEnd, Token *newLocation)
{
/**[newLocation] -> b -> c -> [srcStart] -> [srcEnd] -> f */

View File

@ -178,6 +178,16 @@ public:
**/
static std::size_t getStrLength(const Token *tok);
/**
* Return char of C-string at index (possible escaped "\\n")
*
* Should be called for %str% tokens only.
*
* @param tok token with C-string
* @param index position of character
**/
static std::string getCharAt(const Token *tok, std::size_t index);
Type type() const {
return _type;
}

View File

@ -3244,6 +3244,8 @@ bool Tokenizer::simplifyTokenList()
// clear the _functionList so it can't contain dead pointers
deleteSymbolDatabase();
simplifyCharAt();
// simplify references
simplifyReference();
@ -6661,6 +6663,21 @@ bool Tokenizer::simplifyRedundantParenthesis()
return ret;
}
void Tokenizer::simplifyCharAt()
{
// Replace "string"[0] with 's'
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "%str% [ %num% ]")) {
const MathLib::bigint index = MathLib::toLongNumber(tok->tokAt(2)->str());
// Check within range
if (index >= 0 && index <= (MathLib::bigint)Token::getStrLength(tok)) {
tok->str(std::string("'" + Token::getCharAt(tok, (size_t)index) + "'"));
tok->deleteNext(3);
}
}
}
}
void Tokenizer::simplifyReference()
{
if (isC())

View File

@ -400,6 +400,8 @@ public:
*/
bool simplifyRedundantParenthesis();
void simplifyCharAt();
/** Simplify references */
void simplifyReference();

View File

@ -433,6 +433,7 @@ private:
TEST_CASE(undefinedSizeArray);
TEST_CASE(simplifyArrayAddress); // Replace "&str[num]" => "(str + num)"
TEST_CASE(simplifyCharAt);
}
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Unspecified) {
@ -8046,6 +8047,18 @@ private:
// Don't crash
tok("int", true);
}
void simplifyCharAt() { // ticket #4481
ASSERT_EQUALS("'h' ;", tok("\"hello\"[0] ;"));
ASSERT_EQUALS("'\n' ;", tok("\"\n\"[0] ;"));
ASSERT_EQUALS("'\\0' ;", tok("\"hello\"[5] ;"));
ASSERT_EQUALS("'\\0' ;", tok("\"\"[0] ;"));
ASSERT_EQUALS("'\\0' ;", tok("\"\\0\"[0] ;"));
ASSERT_EQUALS("'\\n' ;", tok("\"hello\\nworld\"[5] ;"));
ASSERT_EQUALS("'w' ;", tok("\"hello\nworld\"[6] ;"));
ASSERT_EQUALS("\"hello\" [ 7 ] ;", tok("\"hello\"[7] ;"));
ASSERT_EQUALS("\"hello\" [ -1 ] ;", tok("\"hello\"[-1] ;"));
}
};
REGISTER_TEST(TestSimplifyTokens)