ValueFlow: Template arguments have 'possible' values

This commit is contained in:
Daniel Marjamäki 2018-01-11 14:22:27 +01:00
parent bbeff99cc3
commit 6fd157e93b
2 changed files with 30 additions and 17 deletions

View File

@ -670,20 +670,24 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
{ {
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
ValueFlow::Value value(MathLib::toLongNumber(tok->str())); ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value, settings); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (tok->isNumber() && MathLib::isFloat(tok->str())) { } else if (tok->isNumber() && MathLib::isFloat(tok->str())) {
ValueFlow::Value value; ValueFlow::Value value;
value.valueType = ValueFlow::Value::FLOAT; value.valueType = ValueFlow::Value::FLOAT;
value.floatValue = MathLib::toDoubleNumber(tok->str()); value.floatValue = MathLib::toDoubleNumber(tok->str());
if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value, settings); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (tok->enumerator() && tok->enumerator()->value_known) { } else if (tok->enumerator() && tok->enumerator()->value_known) {
ValueFlow::Value value(tok->enumerator()->value); ValueFlow::Value value(tok->enumerator()->value);
if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value, settings); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) { } else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
ValueFlow::Value value(0); ValueFlow::Value value(0);
if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok), value, settings); setTokenValue(const_cast<Token *>(tok), value, settings);
} else if (Token::simpleMatch(tok, "sizeof (")) { } else if (Token::simpleMatch(tok, "sizeof (")) {
@ -695,7 +699,7 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
size = getSizeOfType(type, settings); size = getSizeOfType(type, settings);
} }
ValueFlow::Value value(size); ValueFlow::Value value(size);
if (settings->platformType != cppcheck::Platform::Unspecified) if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
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);
@ -708,7 +712,7 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
} }
} }
ValueFlow::Value value(size); ValueFlow::Value value(size);
if (settings->platformType != cppcheck::Platform::Unspecified) if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
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);
@ -724,7 +728,7 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
sz1->variable()->dimensionKnown(0) && sz1->variable()->dimensionKnown(0) &&
(Token::Match(sz2, "* %varid% )", varid1) || Token::Match(sz2, "%varid% [ 0 ] )", varid1))) { (Token::Match(sz2, "* %varid% )", varid1) || Token::Match(sz2, "%varid% [ 0 ] )", varid1))) {
ValueFlow::Value value(sz1->variable()->dimension(0)); ValueFlow::Value value(sz1->variable()->dimension(0));
if (settings->platformType != cppcheck::Platform::Unspecified) if (!tok2->isTemplateArg() && settings->platformType != cppcheck::Platform::Unspecified)
value.setKnown(); value.setKnown();
setTokenValue(const_cast<Token *>(tok->tokAt(4)), value, settings); setTokenValue(const_cast<Token *>(tok->tokAt(4)), value, settings);
} }
@ -732,42 +736,42 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
const ValueType &vt = ValueType::parseDecl(tok2,settings); const ValueType &vt = ValueType::parseDecl(tok2,settings);
if (vt.pointer) { if (vt.pointer) {
ValueFlow::Value value(settings->sizeof_pointer); ValueFlow::Value value(settings->sizeof_pointer);
if (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);
} else if (vt.type == ValueType::Type::CHAR) { } else if (vt.type == ValueType::Type::CHAR) {
ValueFlow::Value value(1); ValueFlow::Value value(1);
if (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);
} else if (vt.type == ValueType::Type::SHORT) { } else if (vt.type == ValueType::Type::SHORT) {
ValueFlow::Value value(settings->sizeof_short); ValueFlow::Value value(settings->sizeof_short);
if (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);
} else if (vt.type == ValueType::Type::INT) { } else if (vt.type == ValueType::Type::INT) {
ValueFlow::Value value(settings->sizeof_int); ValueFlow::Value value(settings->sizeof_int);
if (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);
} else if (vt.type == ValueType::Type::LONG) { } else if (vt.type == ValueType::Type::LONG) {
ValueFlow::Value value(settings->sizeof_long); ValueFlow::Value value(settings->sizeof_long);
if (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);
} else if (vt.type == ValueType::Type::LONGLONG) { } else if (vt.type == ValueType::Type::LONGLONG) {
ValueFlow::Value value(settings->sizeof_long_long); ValueFlow::Value value(settings->sizeof_long_long);
if (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);
} else if (vt.type == ValueType::Type::FLOAT) { } else if (vt.type == ValueType::Type::FLOAT) {
ValueFlow::Value value(settings->sizeof_float); ValueFlow::Value value(settings->sizeof_float);
if (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);
} else if (vt.type == ValueType::Type::DOUBLE) { } else if (vt.type == ValueType::Type::DOUBLE) {
ValueFlow::Value value(settings->sizeof_double); ValueFlow::Value value(settings->sizeof_double);
if (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);
} }
@ -789,12 +793,14 @@ static void valueFlowNumber(TokenList *tokenlist)
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
if (tok->isName() && !tok->varId() && Token::Match(tok, "false|true")) { if (tok->isName() && !tok->varId() && Token::Match(tok, "false|true")) {
ValueFlow::Value value(tok->str() == "true"); ValueFlow::Value value(tok->str() == "true");
if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok, value, tokenlist->getSettings()); setTokenValue(tok, value, tokenlist->getSettings());
} else if (Token::Match(tok, "[(,] NULL [,)]")) { } else if (Token::Match(tok, "[(,] NULL [,)]")) {
// NULL function parameters are not simplified in the // NULL function parameters are not simplified in the
// normal tokenlist // normal tokenlist
ValueFlow::Value value(0); ValueFlow::Value value(0);
if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok->next(), value, tokenlist->getSettings()); setTokenValue(tok->next(), value, tokenlist->getSettings());
} }

View File

@ -2622,6 +2622,13 @@ private:
ASSERT_EQUALS(true, testValueOfX(code, 4U, 6)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 6));
ASSERT_EQUALS(false, testValueOfX(code, 4U, 7)); ASSERT_EQUALS(false, testValueOfX(code, 4U, 7));
ASSERT(value.isKnown()); ASSERT(value.isKnown());
// template parameters are not known
code = "template <int X> void f() { a = X; }\n"
"f<1>();";
value = valueOfTok(code, "1");
ASSERT_EQUALS(1, value.intvalue);
ASSERT_EQUALS(false, value.isKnown());
} }
void valueFlowSizeofForwardDeclaredEnum() { void valueFlowSizeofForwardDeclaredEnum() {