Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed #13513 - adjusted access of known int values #7181

Merged
merged 11 commits into from
Mar 22, 2025
Merged
16 changes: 8 additions & 8 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ static bool match(const Token *tok, const std::string &rhs)
{
if (tok->str() == rhs)
return true;
if (!tok->varId() && tok->hasKnownIntValue() && MathLib::toString(tok->values().front().intvalue) == rhs)
if (!tok->varId() && tok->hasKnownIntValue() && MathLib::toString(tok->getKnownIntValue()) == rhs)
return true;
return false;
}
Expand Down Expand Up @@ -1524,7 +1524,7 @@ bool isUsedAsBool(const Token* const tok, const Settings& settings)
if (parent->isUnaryOp("*"))
return isUsedAsBool(parent, settings);
if (Token::Match(parent, "==|!=") && (tok->astSibling()->isNumber() || tok->astSibling()->isKeyword()) && tok->astSibling()->hasKnownIntValue() &&
tok->astSibling()->values().front().intvalue == 0)
tok->astSibling()->getKnownIntValue() == 0)
return true;
if (parent->str() == "(" && astIsRHS(tok) && Token::Match(parent->astOperand1(), "if|while"))
return true;
Expand Down Expand Up @@ -1656,11 +1656,11 @@ bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Se
const Token* varTok1 = nullptr;
const Token* varTok2 = exprTok;
const ValueFlow::Value* value = nullptr;
if (condTok->astOperand1()->hasKnownIntValue()) {
value = &condTok->astOperand1()->values().front();
if (const ValueFlow::Value* vi1 = condTok->astOperand1()->getKnownValue(ValueFlow::Value::ValueType::INT)) {
value = vi1;
varTok1 = condTok->astOperand2();
} else if (condTok->astOperand2()->hasKnownIntValue()) {
value = &condTok->astOperand2()->values().front();
} else if (const ValueFlow::Value* vi2 = condTok->astOperand2()->getKnownValue(ValueFlow::Value::ValueType::INT)) {
value = vi2;
varTok1 = condTok->astOperand1();
}
const bool exprIsNot = Token::simpleMatch(exprTok, "!");
Expand Down Expand Up @@ -3715,8 +3715,8 @@ static std::set<MathLib::bigint> getSwitchValues(const Token *startbrace, bool &
}
if (Token::simpleMatch(tok, "case")) {
const Token *valueTok = tok->astOperand1();
if (valueTok->hasKnownIntValue())
values.insert(valueTok->getKnownIntValue());
if (const ValueFlow::Value* v = valueTok->getKnownValue(ValueFlow::Value::ValueType::INT))
values.insert(v->intvalue);
continue;
}
}
Expand Down
10 changes: 4 additions & 6 deletions lib/checkbufferoverrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ static std::vector<ValueFlow::Value> getOverrunIndexValues(const Token* tok,
? ValueFlow::isOutOfBounds(makeSizeValue(size, path), indexTokens[i])
: std::vector<ValueFlow::Value>{};
if (values.empty()) {
if (indexTokens[i]->hasKnownIntValue())
indexValues.push_back(indexTokens[i]->values().front());
if (const ValueFlow::Value* v = indexTokens[i]->getKnownValue(ValueFlow::Value::ValueType::INT))
indexValues.push_back(*v);
else
indexValues.push_back(ValueFlow::Value::unknown());
continue;
Expand Down Expand Up @@ -1065,12 +1065,10 @@ void CheckBufferOverrun::objectIndex()
const Token *idx = tok->astOperand2();
if (!idx || !obj)
continue;
if (idx->hasKnownIntValue()) {
if (idx->getKnownIntValue() == 0)
if (const ValueFlow::Value* v = idx->getKnownValue(ValueFlow::Value::ValueType::INT)) {
if (v->intvalue == 0)
continue;
}
if (idx->hasKnownIntValue() && idx->getKnownIntValue() == 0)
continue;
Comment on lines 1071 to -1073
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I filed https://trac.cppcheck.net/ticket/13732 about detecting this.


std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(obj, false, -1);
for (const ValueFlow::Value& v:values) {
Expand Down
10 changes: 5 additions & 5 deletions lib/checkcondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ void CheckCondition::checkBadBitmaskCheck()
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while")) ||
(parent->str() == "return" && parent->astOperand1() == tok && inBooleanFunction(tok));

const bool isTrue = (tok->astOperand1()->hasKnownIntValue() && tok->astOperand1()->values().front().intvalue != 0) ||
(tok->astOperand2()->hasKnownIntValue() && tok->astOperand2()->values().front().intvalue != 0);
const bool isTrue = (tok->astOperand1()->hasKnownIntValue() && tok->astOperand1()->getKnownIntValue() != 0) ||
(tok->astOperand2()->hasKnownIntValue() && tok->astOperand2()->getKnownIntValue() != 0);

if (isBoolean && isTrue)
badBitmaskCheckError(tok);
Expand All @@ -333,8 +333,8 @@ void CheckCondition::checkBadBitmaskCheck()
if (mTokenizer->hasIfdef(startStop.first, startStop.second))
continue;

const bool isZero1 = (tok->astOperand1()->hasKnownIntValue() && tok->astOperand1()->values().front().intvalue == 0);
const bool isZero2 = (tok->astOperand2()->hasKnownIntValue() && tok->astOperand2()->values().front().intvalue == 0);
const bool isZero1 = (tok->astOperand1()->hasKnownIntValue() && tok->astOperand1()->getKnownIntValue() == 0);
const bool isZero2 = (tok->astOperand2()->hasKnownIntValue() && tok->astOperand2()->getKnownIntValue() == 0);
if (!isZero1 && !isZero2)
continue;

Expand Down Expand Up @@ -1700,7 +1700,7 @@ void CheckCondition::checkInvalidTestForOverflow()
const Token * const other = expr->astSibling();

// x [+-] c cmp x
if ((other->isNumber() && other->getKnownIntValue() > 0) ||
if ((other->isNumber() && other->hasKnownIntValue() && other->getKnownIntValue() > 0) ||
(!other->isNumber() && other->valueType() && other->valueType()->isIntegral() && other->valueType()->sign == ValueType::Sign::UNSIGNED)) {
bool result;
if (lhs->str() == "+")
Expand Down
4 changes: 2 additions & 2 deletions lib/checkleakautovar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
tok = tok->next();
while (Token::Match(tok, "%name% ::|.") || (startparen && Token::Match(tok, "%name% ,")))
tok = tok->tokAt(2);
const bool isnull = tok->hasKnownIntValue() && tok->values().front().intvalue == 0;
const bool isnull = tok->hasKnownIntValue() && tok->getKnownIntValue() == 0;
if (!isnull && tok->varId() && tok->strAt(1) != "[") {
const VarInfo::AllocInfo allocation(arrayDelete ? NEW_ARRAY : NEW, VarInfo::DEALLOC, delTok);
changeAllocStatus(varInfo, allocation, tok, tok);
Expand Down Expand Up @@ -1035,7 +1035,7 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
if (isAddressOf)
arg = arg->next();

const bool isnull = !isAddressOf && (arg->hasKnownIntValue() && arg->values().front().intvalue == 0);
const bool isnull = !isAddressOf && (arg->hasKnownIntValue() && arg->getKnownIntValue() == 0);

// Is variable allocated?
if (!isnull && (!af || af->arg == argNr)) {
Expand Down
2 changes: 1 addition & 1 deletion lib/checknullpointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ void CheckNullPointer::nullConstantDereference()
const Token *argtok = args[argnr];
if (!argtok->hasKnownIntValue())
continue;
if (argtok->values().front().intvalue != 0)
if (argtok->getKnownIntValue() != 0)
continue;
if (mSettings->library.isnullargbad(tok, argnr+1))
nullPointerError(argtok);
Expand Down
6 changes: 3 additions & 3 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ void CheckOther::warningOldStylePointerCast()
tok = tok->next();

const Token *p = tok->tokAt(4);
if (p->hasKnownIntValue() && p->values().front().intvalue==0) // Casting nullpointers is safe
if (p->hasKnownIntValue() && p->getKnownIntValue()==0) // Casting nullpointers is safe
continue;

if (typeTok->tokType() == Token::eType || typeTok->tokType() == Token::eName)
Expand Down Expand Up @@ -1399,8 +1399,8 @@ static bool isLargeContainer(const Variable* var, const Settings* settings)
const std::size_t maxByValueSize = 2 * settings->platform.sizeof_pointer;
if (var->dimensions().empty()) {
if (vt->container->startPattern == "std :: bitset <") {
if (vt->containerTypeToken->hasKnownIntValue())
return vt->containerTypeToken->getKnownIntValue() / 8 > maxByValueSize;
if (const ValueFlow::Value* v = vt->containerTypeToken->getKnownValue(ValueFlow::Value::ValueType::INT))
return v->intvalue / 8 > maxByValueSize;
}
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions lib/checkstl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ bool CheckStl::isContainerSizeGE(const Token * containerToken, const Token *expr
mul = expr->astOperand1();
else
return false;
return mul && (!mul->hasKnownIntValue() || mul->values().front().intvalue != 0);
return mul && (!mul->hasKnownIntValue() || mul->getKnownIntValue() != 0);
}
if (expr->str() == "+") {
const Token *op;
Expand Down Expand Up @@ -2492,7 +2492,7 @@ void CheckStl::checkDereferenceInvalidIterator2()
if (cValue && cValue->intvalue == 0) {
if (Token::Match(tok->astParent(), "+|-") && astIsIntegral(tok->astSibling(), false)) {
if (tok->astSibling() && tok->astSibling()->hasKnownIntValue()) {
if (tok->astSibling()->values().front().intvalue == 0)
if (tok->astSibling()->getKnownIntValue() == 0)
continue;
} else {
advanceIndex = tok->astSibling();
Expand Down Expand Up @@ -2906,8 +2906,8 @@ namespace {
alwaysFalse = false;
return;
}
(returnTok->values().front().intvalue ? alwaysTrue : alwaysFalse) &= true;
(returnTok->values().front().intvalue ? alwaysFalse : alwaysTrue) &= false;
(returnTok->getKnownIntValue() ? alwaysTrue : alwaysFalse) &= true;
(returnTok->getKnownIntValue() ? alwaysFalse : alwaysTrue) &= false;
});
if (alwaysTrue == alwaysFalse)
return "";
Expand Down
5 changes: 2 additions & 3 deletions lib/checktype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,8 @@ void CheckType::checkLongCast()
if (tok->str() != "=" || !Token::Match(tok->astOperand2(), "*|<<") || tok->astOperand2()->isUnaryOp("*"))
continue;

if (tok->astOperand2()->hasKnownIntValue()) {
const ValueFlow::Value &v = tok->astOperand2()->values().front();
if (mSettings->platform.isIntValue(v.intvalue))
if (const ValueFlow::Value* v = tok->astOperand2()->getKnownValue(ValueFlow::Value::ValueType::INT)) {
if (mSettings->platform.isIntValue(v->intvalue))
continue;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/checkuninitvar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::map<nonneg i
if (!tok)
return;

if (tok->hasKnownIntValue()) {
if (tok->getKnownIntValue() == 0)
if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::INT)) {
if (v->intvalue == 0)
*alwaysFalse = true;
else
*alwaysTrue = true;
Expand Down
2 changes: 1 addition & 1 deletion lib/forwardanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ namespace {
if (!condTok->hasKnownIntValue() || inLoop) {
if (!analyzer->lowerToPossible())
return Break(Analyzer::Terminate::Bail);
} else if (condTok->values().front().intvalue == inElse) {
} else if (condTok->getKnownIntValue() == inElse) {
return Break();
}
// Handle loop
Expand Down
4 changes: 2 additions & 2 deletions lib/fwdanalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *
const Token *bodyStart = tok->linkAt(1)->next();
const Token *conditionStart = tok->next();
const Token *condTok = conditionStart->astOperand2();
if (condTok->hasKnownIntValue()) {
const bool cond = !!condTok->values().front().intvalue;
if (const ValueFlow::Value* v = condTok->getKnownValue(ValueFlow::Value::ValueType::INT)) {
const bool cond = !!v->intvalue;
if (cond) {
FwdAnalysis::Result result = checkRecursive(expr, bodyStart, bodyStart->link(), exprVarIds, local, true, depth);
if (result.type != Result::Type::NONE)
Expand Down
4 changes: 2 additions & 2 deletions lib/pathanalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ static const Token* assignExpr(const Token* tok)

std::pair<bool, bool> PathAnalysis::checkCond(const Token * tok, bool& known)
{
if (tok->hasKnownIntValue()) {
if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::INT)) {
known = true;
return std::make_pair(!!tok->values().front().intvalue, !tok->values().front().intvalue);
return std::make_pair(!!v->intvalue, !v->intvalue);
}
auto it = std::find_if(tok->values().cbegin(), tok->values().cend(), [](const ValueFlow::Value& v) {
return v.isIntValue();
Expand Down
10 changes: 5 additions & 5 deletions lib/programmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ void ProgramMemory::setValue(const Token* expr, const ValueFlow::Value& value) {
const Token* subexpr = solveExprValue(
expr,
[&](const Token* tok) -> std::vector<MathLib::bigint> {
if (tok->hasKnownIntValue())
return {tok->values().front().intvalue};
if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::INT))
return {v->intvalue};
MathLib::bigint result = 0;
if (getIntValue(tok->exprId(), result))
return {result};
Expand Down Expand Up @@ -305,8 +305,8 @@ static void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, con
auto eval = [&](const Token* t) -> std::vector<MathLib::bigint> {
if (!t)
return std::vector<MathLib::bigint>{};
if (t->hasKnownIntValue())
return {t->values().front().intvalue};
if (const ValueFlow::Value* v = t->getKnownValue(ValueFlow::Value::ValueType::INT))
return {v->intvalue};
MathLib::bigint result = 0;
bool error = false;
execute(t, pm, &result, &error, settings);
Expand Down Expand Up @@ -1372,7 +1372,7 @@ namespace {
if (!expr)
return unknown();
if (expr->hasKnownIntValue() && !expr->isAssignmentOp() && expr->str() != ",")
return expr->values().front();
return *expr->getKnownValue(ValueFlow::Value::ValueType::INT);
if ((value = expr->getKnownValue(ValueFlow::Value::ValueType::FLOAT)) ||
(value = expr->getKnownValue(ValueFlow::Value::ValueType::TOK)) ||
(value = expr->getKnownValue(ValueFlow::Value::ValueType::ITERATOR_START)) ||
Expand Down
18 changes: 11 additions & 7 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,8 +1815,8 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow()
if (!tok->isName())
tokenList.addtoken(tok->str(), 0, 0, 0, false);

else if (tok->hasKnownIntValue())
tokenList.addtoken(MathLib::toString(tok->getKnownIntValue()), 0, 0, 0, false);
else if (const ValueFlow::Value* v = tok->getKnownValue(ValueFlow::Value::ValueType::INT))
tokenList.addtoken(MathLib::toString(v->intvalue), 0, 0, 0, false);

else {
fail = true;
Expand Down Expand Up @@ -1848,9 +1848,9 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow()
dimension.known = false;

// check for a single token dimension
if (dimension.tok->hasKnownIntValue()) {
if (const ValueFlow::Value* v = dimension.tok->getKnownValue(ValueFlow::Value::ValueType::INT)) {
dimension.known = true;
dimension.num = dimension.tok->getKnownIntValue();
dimension.num = v->intvalue;
continue;
}

Expand Down Expand Up @@ -3746,9 +3746,13 @@ bool Variable::arrayDimensions(const Settings& settings, bool& isContainer)
// TODO: only perform when ValueFlow is enabled
// TODO: collect timing information for this call?
ValueFlow::valueFlowConstantFoldAST(const_cast<Token *>(dimension_.tok), settings);
if (dimension_.tok && (dimension_.tok->hasKnownIntValue() ||
(dimension_.tok->isTemplateArg() && !dimension_.tok->values().empty()))) {
dimension_.num = dimension_.tok->getKnownIntValue();
if (dimension_.tok) {
if (const ValueFlow::Value* v = dimension_.tok->getKnownValue(ValueFlow::Value::ValueType::INT))
dimension_.num = v->intvalue;
else if (dimension_.tok->isTemplateArg() && !dimension_.tok->values().empty()) {
assert(dimension_.tok->values().size() == 1);
dimension_.num = dimension_.tok->values().front().intvalue;
}
dimension_.known = true;
}
}
Expand Down
17 changes: 14 additions & 3 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2503,13 +2503,15 @@ std::shared_ptr<ScopeInfo2> Token::scopeInfo() const
return mImpl->mScopeInfo;
}

// if there is a known INT value it will always be the first entry
bool Token::hasKnownIntValue() const
{
if (!mImpl->mValues)
return false;
return std::any_of(mImpl->mValues->begin(), mImpl->mValues->end(), [](const ValueFlow::Value& value) {
return value.isKnown() && value.isIntValue();
});
if (mImpl->mValues->empty())
return false;
const ValueFlow::Value& value = mImpl->mValues->front();
return value.isIntValue() && value.isKnown();
}

bool Token::hasKnownValue() const
Expand Down Expand Up @@ -2540,6 +2542,15 @@ const ValueFlow::Value* Token::getKnownValue(ValueFlow::Value::ValueType t) cons
{
if (!mImpl->mValues)
return nullptr;
if (mImpl->mValues->empty())
return nullptr;
// known INT values are always the first entry
if (t == ValueFlow::Value::ValueType::INT) {
const auto& v = mImpl->mValues->front();
if (!v.isKnown() || !v.isIntValue())
return nullptr;
return &v;
}
auto it = std::find_if(mImpl->mValues->begin(), mImpl->mValues->end(), [&](const ValueFlow::Value& value) {
return value.isKnown() && value.valueType == t;
});
Expand Down
3 changes: 3 additions & 0 deletions lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,9 @@ class CPPCHECKLIB Token {

const ValueFlow::Value* getKnownValue(ValueFlow::Value::ValueType t) const;
MathLib::bigint getKnownIntValue() const {
assert(!mImpl->mValues->empty());
assert(mImpl->mValues->front().isKnown());
assert(mImpl->mValues->front().valueType == ValueFlow::Value::ValueType::INT);
return mImpl->mValues->front().intvalue;
}

Expand Down
Loading
Loading