ValueFlow: Improved handling of strings

This commit is contained in:
Daniel Marjamäki 2015-02-07 18:14:22 +01:00
parent dd70b6e0cd
commit 62a5d88eb0
2 changed files with 46 additions and 0 deletions

View File

@ -374,12 +374,29 @@ static void valueFlowNumber(TokenList *tokenlist)
static void valueFlowString(TokenList *tokenlist)
{
std::map<unsigned int, const Token *> constantStrings;
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
if (tok->type() == Token::eString) {
ValueFlow::Value strvalue;
strvalue.tokvalue = tok;
setTokenValue(tok, strvalue);
}
if (Token::Match(tok, "const char %var% [ %num%| ] = %str% ;")) {
const Token *vartok = tok->tokAt(2);
const Token *strtok = tok->linkAt(3)->tokAt(2);
constantStrings[vartok->varId()] = strtok;
}
if (tok->varId() > 0U) {
const std::map<unsigned int, const Token *>::const_iterator it = constantStrings.find(tok->varId());
if (it != constantStrings.end()) {
ValueFlow::Value strvalue;
strvalue.tokvalue = it->second;
setTokenValue(tok, strvalue);
}
}
}
}
@ -1337,6 +1354,27 @@ static void execute(const Token *expr,
execute(expr->astOperand2(), programMemory, result, error);
}
else if (expr->str() == "[" && expr->astOperand1() && expr->astOperand2()) {
if (expr->astOperand1()->values.size() != 1U) {
*error = true;
return;
}
const ValueFlow::Value val = expr->astOperand1()->values.front();
if (!val.tokvalue || !val.tokvalue->isLiteral()) {
*error = true;
return;
}
const std::string strValue = val.tokvalue->strValue();
MathLib::bigint index = 0;
execute(expr->astOperand2(), programMemory, &index, error);
if (index >= 0 && index < (int)strValue.size())
*result = strValue[index];
else if (index == (int)strValue.size())
*result = 0;
else
*error = true;
}
else
*error = true;
}

View File

@ -1244,6 +1244,14 @@ private:
"}";
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
code = "void f() {\n"
" const char abc[] = \"abc\";\n"
" int x;\n"
" for (x = 0; abc[x] != '\\0'; x++) {}\n"
" a[x] = 0;\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 5U, 3));
code = "void f() {\n" // #5939
" int x;\n"
" for (int x = 0; (x = do_something()) != 0;)\n"