ValueFlow: Improved handling of strings
This commit is contained in:
parent
dd70b6e0cd
commit
62a5d88eb0
|
@ -374,12 +374,29 @@ static void valueFlowNumber(TokenList *tokenlist)
|
||||||
|
|
||||||
static void valueFlowString(TokenList *tokenlist)
|
static void valueFlowString(TokenList *tokenlist)
|
||||||
{
|
{
|
||||||
|
std::map<unsigned int, const Token *> constantStrings;
|
||||||
|
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
||||||
if (tok->type() == Token::eString) {
|
if (tok->type() == Token::eString) {
|
||||||
ValueFlow::Value strvalue;
|
ValueFlow::Value strvalue;
|
||||||
strvalue.tokvalue = tok;
|
strvalue.tokvalue = tok;
|
||||||
setTokenValue(tok, strvalue);
|
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);
|
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
|
else
|
||||||
*error = true;
|
*error = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1244,6 +1244,14 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
|
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
|
code = "void f() {\n" // #5939
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
" for (int x = 0; (x = do_something()) != 0;)\n"
|
" for (int x = 0; (x = do_something()) != 0;)\n"
|
||||||
|
|
Loading…
Reference in New Issue