ValueFlow: fix handling of sizeof(*p)

This commit is contained in:
Daniel Marjamäki 2019-03-11 20:32:24 +01:00
parent 17253cdb55
commit 7b17b33a49
2 changed files with 44 additions and 38 deletions

View File

@ -828,6 +828,28 @@ static unsigned int getSizeOfType(const Token *typeTok, const Settings *settings
return 0; return 0;
} }
static size_t getSizeOf(const ValueType &vt, const Settings *settings)
{
if (vt.pointer)
return settings->sizeof_pointer;
else if (vt.type == ValueType::Type::CHAR)
return 1;
else if (vt.type == ValueType::Type::SHORT)
return settings->sizeof_short;
else if (vt.type == ValueType::Type::INT)
return settings->sizeof_int;
else if (vt.type == ValueType::Type::LONG)
return settings->sizeof_long;
else if (vt.type == ValueType::Type::LONGLONG)
return settings->sizeof_long_long;
else if (vt.type == ValueType::Type::FLOAT)
return settings->sizeof_float;
else if (vt.type == ValueType::Type::DOUBLE)
return settings->sizeof_double;
return 0;
}
// Handle various constants.. // Handle various constants..
static Token * valueFlowSetConstantValue(const Token *tok, const Settings *settings, bool cpp) static Token * valueFlowSetConstantValue(const Token *tok, const Settings *settings, bool cpp)
{ {
@ -862,7 +884,16 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
else else
tok2 = tok2->tokAt(2); tok2 = tok2->tokAt(2);
} }
if (tok2->enumerator() && tok2->enumerator()->scope) { if (Token::Match(tok, "sizeof ( *")) {
const ValueType *vt = tok->tokAt(2)->valueType();
const size_t sz = vt ? getSizeOf(*vt, settings) : 0;
if (sz > 0) {
ValueFlow::Value value(sz);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
}
} else if (tok2->enumerator() && tok2->enumerator()->scope) {
long long size = settings->sizeof_int; long long size = settings->sizeof_int;
const Token * type = tok2->enumerator()->scope->enumType; const Token * type = tok2->enumerator()->scope->enumType;
if (type) { if (type) {
@ -933,43 +964,9 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
} }
} else if (!tok2->type()) { } else if (!tok2->type()) {
const ValueType &vt = ValueType::parseDecl(tok2,settings); const ValueType &vt = ValueType::parseDecl(tok2,settings);
if (vt.pointer) { const size_t sz = getSizeOf(vt, settings);
ValueFlow::Value value(settings->sizeof_pointer); if (sz > 0) {
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified) ValueFlow::Value value(sz);
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::CHAR) {
ValueFlow::Value value(1);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::SHORT) {
ValueFlow::Value value(settings->sizeof_short);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::INT) {
ValueFlow::Value value(settings->sizeof_int);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::LONG) {
ValueFlow::Value value(settings->sizeof_long);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::LONGLONG) {
ValueFlow::Value value(settings->sizeof_long_long);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::FLOAT) {
ValueFlow::Value value(settings->sizeof_float);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
} else if (vt.type == ValueType::Type::DOUBLE) {
ValueFlow::Value value(settings->sizeof_double);
if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified) if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok->next()), value, settings); setTokenValue(const_cast<Token *>(tok->next()), value, settings);

View File

@ -752,6 +752,15 @@ private:
const char *code; const char *code;
std::list<ValueFlow::Value> values; std::list<ValueFlow::Value> values;
// array size
code = "void f() {\n"
" char a[10];"
" x = sizeof(*a);\n"
"}";
values = tokenValues(code,"( *");
ASSERT_EQUALS(1U, values.size());
ASSERT_EQUALS(1, values.back().intvalue);
#define CHECK(A, B) \ #define CHECK(A, B) \
code = "void f() {\n" \ code = "void f() {\n" \
" x = sizeof(" A ");\n" \ " x = sizeof(" A ");\n" \