ValueFlow: Improved handling of sizeof
This commit is contained in:
parent
461e5cc5c9
commit
17aaecbd6b
|
@ -4650,6 +4650,13 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Sett
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueType ValueType::parseDecl(const Token *type, const Settings *settings)
|
||||||
|
{
|
||||||
|
ValueType vt;
|
||||||
|
parsedecl(type, &vt, settings->defaultSign == 'u' ? Sign::UNSIGNED : Sign::SIGNED, settings);
|
||||||
|
return vt;
|
||||||
|
}
|
||||||
|
|
||||||
bool ValueType::fromLibraryType(const std::string &typestr, const Settings *settings)
|
bool ValueType::fromLibraryType(const std::string &typestr, const Settings *settings)
|
||||||
{
|
{
|
||||||
const Library::PodType* podtype = settings->library.podtype(typestr);
|
const Library::PodType* podtype = settings->library.podtype(typestr);
|
||||||
|
|
|
@ -1153,6 +1153,8 @@ public:
|
||||||
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr) {}
|
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr) {}
|
||||||
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), originalTypeName(otn) {}
|
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), originalTypeName(otn) {}
|
||||||
|
|
||||||
|
static ValueType parseDecl(const Token *type, const Settings *settings);
|
||||||
|
|
||||||
bool isIntegral() const {
|
bool isIntegral() const {
|
||||||
return (type >= ValueType::Type::BOOL && type <= ValueType::Type::UNKNOWN_INT);
|
return (type >= ValueType::Type::BOOL && type <= ValueType::Type::UNKNOWN_INT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -649,7 +649,7 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
|
||||||
ValueFlow::Value value(0);
|
ValueFlow::Value value(0);
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
setTokenValue(const_cast<Token *>(tok), value, settings);
|
setTokenValue(const_cast<Token *>(tok), value, settings);
|
||||||
} else if (Token::simpleMatch(tok, "sizeof (") && tok->tokAt(2)) {
|
} else if (Token::simpleMatch(tok, "sizeof (")) {
|
||||||
const Token *tok2 = tok->tokAt(2);
|
const Token *tok2 = tok->tokAt(2);
|
||||||
if (tok2->enumerator() && tok2->enumerator()->scope) {
|
if (tok2->enumerator() && tok2->enumerator()->scope) {
|
||||||
long long size = settings->sizeof_int;
|
long long size = settings->sizeof_int;
|
||||||
|
@ -681,6 +681,56 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
setTokenValue(const_cast<Token *>(tok), value, settings);
|
setTokenValue(const_cast<Token *>(tok), value, settings);
|
||||||
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (Token::Match(tok, "sizeof ( %var% ) / sizeof (") && tok->next()->astParent() == tok->tokAt(4)) {
|
||||||
|
// Get number of elements in array
|
||||||
|
const Token *sz1 = tok->tokAt(2);
|
||||||
|
const Token *sz2 = tok->tokAt(7);
|
||||||
|
const unsigned int varid1 = sz1->varId();
|
||||||
|
if (varid1 &&
|
||||||
|
sz1->variable() &&
|
||||||
|
sz1->variable()->isArray() &&
|
||||||
|
!sz1->variable()->dimensions().empty() &&
|
||||||
|
sz1->variable()->dimensionKnown(0) &&
|
||||||
|
(Token::Match(sz2, "* %varid% )", varid1) || Token::Match(sz2, "%varid% [ 0 ] )", varid1))) {
|
||||||
|
ValueFlow::Value value(sz1->variable()->dimension(0));
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->tokAt(4)), value, settings);
|
||||||
|
}
|
||||||
|
} else if (!tok2->type()) {
|
||||||
|
const ValueType &vt = ValueType::parseDecl(tok2,settings);
|
||||||
|
if (vt.pointer) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_pointer);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::CHAR) {
|
||||||
|
ValueFlow::Value value(1);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::SHORT) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_short);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::INT) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_int);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::LONG) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_long);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::LONGLONG) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_long_long);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::FLOAT) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_float);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
} else if (vt.type == ValueType::Type::DOUBLE) {
|
||||||
|
ValueFlow::Value value(settings->sizeof_double);
|
||||||
|
value.setKnown();
|
||||||
|
setTokenValue(const_cast<Token *>(tok->next()), value, settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// skip over enum
|
// skip over enum
|
||||||
tok = tok->linkAt(1);
|
tok = tok->linkAt(1);
|
||||||
|
|
|
@ -480,6 +480,22 @@ private:
|
||||||
ASSERT_EQUALS(1U, values.size());
|
ASSERT_EQUALS(1U, values.size());
|
||||||
ASSERT_EQUALS(-10, values.back().intvalue);
|
ASSERT_EQUALS(-10, values.back().intvalue);
|
||||||
|
|
||||||
|
// sizeof
|
||||||
|
code = "void f() {\n"
|
||||||
|
" x = sizeof(int);\n"
|
||||||
|
"}";
|
||||||
|
values = tokenValues(code,"( int )");
|
||||||
|
ASSERT_EQUALS(1U, values.size());
|
||||||
|
ASSERT_EQUALS(settings.sizeof_int, values.back().intvalue);
|
||||||
|
|
||||||
|
code = "void f() {\n"
|
||||||
|
" struct S *a[10];"
|
||||||
|
" x = sizeof(a) / sizeof(a[0]);\n"
|
||||||
|
"}";
|
||||||
|
values = tokenValues(code,"/");
|
||||||
|
ASSERT_EQUALS(1U, values.size());
|
||||||
|
ASSERT_EQUALS(10, values.back().intvalue);
|
||||||
|
|
||||||
// function call => calculation
|
// function call => calculation
|
||||||
code = "void f(int x) {\n"
|
code = "void f(int x) {\n"
|
||||||
" a = x + 8;\n"
|
" a = x + 8;\n"
|
||||||
|
|
Loading…
Reference in New Issue