Skip to content

Commit 0568587

Browse files
author
Your Name
committed
Simplify
1 parent 2ff811f commit 0568587

3 files changed

Lines changed: 34 additions & 33 deletions

File tree

lib/checkstl.cpp

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3411,29 +3411,36 @@ static bool isUsableValue(const ValueFlow::Value& value, const Settings& setting
34113411
return true;
34123412
}
34133413

3414+
// Get the first ValueFlow value of a token matching the predicate, preferring known values
3415+
template<class Predicate>
3416+
static const ValueFlow::Value* selectPreferredValue(const Token* tok, const Predicate& pred)
3417+
{
3418+
const ValueFlow::Value* result = nullptr;
3419+
for (const ValueFlow::Value& value : tok->values()) {
3420+
if (!pred(value))
3421+
continue;
3422+
if (result && !(value.isKnown() && !result->isKnown()))
3423+
continue;
3424+
result = &value;
3425+
}
3426+
return result;
3427+
}
3428+
34143429
// Get the iterator value of an iterator expression together with the container size value that
34153430
// ValueFlow has added to the iterator
34163431
static IteratorPosition getIteratorPosition(const Token* tok, const Settings& settings)
34173432
{
34183433
IteratorPosition position;
34193434
if (!tok)
34203435
return position;
3421-
for (const ValueFlow::Value& value : tok->values()) {
3422-
if (!isUsableValue(value, settings) || !value.isIteratorValue())
3423-
continue;
3424-
if (position.value && !(value.isKnown() && !position.value->isKnown()))
3425-
continue;
3426-
position.value = &value;
3427-
}
3436+
position.value = selectPreferredValue(tok, [&](const ValueFlow::Value& value) {
3437+
return isUsableValue(value, settings) && value.isIteratorValue();
3438+
});
34283439
if (!position.value)
34293440
return position;
3430-
for (const ValueFlow::Value& value : tok->values()) {
3431-
if (!isUsableValue(value, settings) || !value.isContainerSizeValue() || value.path != position.value->path)
3432-
continue;
3433-
if (position.sizeValue && !(value.isKnown() && !position.sizeValue->isKnown()))
3434-
continue;
3435-
position.sizeValue = &value;
3436-
}
3441+
position.sizeValue = selectPreferredValue(tok, [&](const ValueFlow::Value& value) {
3442+
return isUsableValue(value, settings) && value.isContainerSizeValue() && value.path == position.value->path;
3443+
});
34373444
return position;
34383445
}
34393446

@@ -3485,18 +3492,10 @@ static const ValueFlow::Value* getCountValue(const Token* tok, const Settings& s
34853492
{
34863493
if (!tok)
34873494
return nullptr;
3488-
const ValueFlow::Value* countValue = nullptr;
3489-
for (const ValueFlow::Value& value : tok->values()) {
3490-
if (!isUsableValue(value, settings) || !value.isIntValue())
3491-
continue;
3492-
// the count could be smaller, which would make fewer elements accessed
3493-
if (value.bound == ValueFlow::Value::Bound::Upper)
3494-
continue;
3495-
if (countValue && !(value.isKnown() && !countValue->isKnown()))
3496-
continue;
3497-
countValue = &value;
3498-
}
3499-
return countValue;
3495+
return selectPreferredValue(tok, [&](const ValueFlow::Value& value) {
3496+
// a count with an upper bound could be smaller, which would make fewer elements accessed
3497+
return isUsableValue(value, settings) && value.isIntValue() && value.bound != ValueFlow::Value::Bound::Upper;
3498+
});
35003499
}
35013500

35023501
void CheckStlImpl::algorithmOutOfBounds()
@@ -3548,7 +3547,8 @@ void CheckStlImpl::algorithmOutOfBounds()
35483547
const ValueFlow::Value lastLifetime = getLifetimeIteratorValue(args[1]);
35493548
if (!firstLifetime.tokvalue || !lastLifetime.tokvalue)
35503549
continue;
3551-
if (!isSameExpression(false, firstLifetime.tokvalue, lastLifetime.tokvalue, mSettings, false, false))
3550+
if (!isSameIteratorContainerExpression(
3551+
firstLifetime.tokvalue, lastLifetime.tokvalue, mSettings, firstLifetime.lifetimeKind))
35523552
continue;
35533553
accessed = getIteratorDistance(first, last);
35543554
if (!accessed)
@@ -3593,7 +3593,6 @@ void CheckStlImpl::algorithmOutOfBounds()
35933593
conditionValue ? conditionValue : (dest.sizeValue ? dest.sizeValue : dest.value);
35943594
algorithmOutOfBoundsError(args[argnr],
35953595
"std::" + nameTok->str(),
3596-
args[argnr]->expressionString(),
35973596
accessed.count,
35983597
available.count,
35993598
pathValue,
@@ -3607,14 +3606,14 @@ void CheckStlImpl::algorithmOutOfBounds()
36073606

36083607
void CheckStlImpl::algorithmOutOfBoundsError(const Token* tok,
36093608
const std::string& algoName,
3610-
const std::string& iterExpr,
36113609
MathLib::bigint accessed,
36123610
MathLib::bigint available,
36133611
const ValueFlow::Value* value,
36143612
const Token* condition,
36153613
bool mayAccessFewer,
36163614
bool inconclusive)
36173615
{
3616+
const std::string iterExpr = tok ? tok->expressionString() : "it";
36183617
const std::string accessedStr = MathLib::toString(accessed) + (accessed == 1 ? " element" : " elements");
36193618
const std::string availableStr = MathLib::toString(available) + (available == 1 ? " element is" : " elements are");
36203619
const std::string body = "algorithm '" + algoName + "' " + (mayAccessFewer ? "may access up to " : "accesses ") +
@@ -3782,7 +3781,7 @@ void CheckStl::getErrorMessages(ErrorLogger& errorLogger, const Settings& settin
37823781
c.dereferenceInvalidIteratorError(nullptr, "i");
37833782
// TODO: derefInvalidIteratorRedundantCheck
37843783
c.eraseIteratorOutOfBoundsError(nullptr, nullptr);
3785-
c.algorithmOutOfBoundsError(nullptr, "std::copy", "it", 10, 6, nullptr, nullptr, false, false);
3784+
c.algorithmOutOfBoundsError(nullptr, "std::copy", 10, 6, nullptr, nullptr, false, false);
37863785
c.useStlAlgorithmError(nullptr, "");
37873786
c.knownEmptyContainerError(nullptr, "");
37883787
c.globalLockGuardError(nullptr);

lib/checkstl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ class CPPCHECKLIB CheckStlImpl : public CheckImpl {
245245

246246
void algorithmOutOfBoundsError(const Token* tok,
247247
const std::string& algoName,
248-
const std::string& iterExpr,
249248
MathLib::bigint accessed,
250249
MathLib::bigint available,
251250
const ValueFlow::Value* value,

lib/valueflow.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3844,14 +3844,17 @@ static void valueFlowForwardConst(Token* start,
38443844
{
38453845
if (!precedes(start, end))
38463846
throw InternalError(var->nameToken(), "valueFlowForwardConst: start token does not precede the end token.");
3847+
const bool hasContainerSizeValue = std::any_of(values.begin(), values.end(), [](const ValueFlow::Value& value) {
3848+
return value.isContainerSizeValue();
3849+
});
38473850
for (Token* tok = start; tok != end; tok = tok->next()) {
38483851
if (tok->varId() == var->declarationId()) {
38493852
for (const ValueFlow::Value& value : values)
38503853
setTokenValue(tok, value, settings);
38513854
} else {
38523855
[&] {
3853-
// Add the container size to iterators of the container
3854-
if (astIsIterator(tok) && isAliasOf(tok, var->declarationId())) {
3856+
// Add the container size to iterators of the container (mirrors ContainerExpressionAnalyzer::match)
3857+
if (hasContainerSizeValue && astIsIterator(tok) && isAliasOf(tok, var->declarationId())) {
38553858
for (const ValueFlow::Value& value : values) {
38563859
if (!value.isContainerSizeValue())
38573860
continue;

0 commit comments

Comments
 (0)