Fix issue 10120: FP: containerOutOfBounds, regression (#3064)
This commit is contained in:
parent
8b26ecbcdd
commit
d05acf3c41
|
@ -42,6 +42,7 @@ struct Analyzer {
|
|||
Inconclusive = (1 << 3),
|
||||
Match = (1 << 4),
|
||||
Idempotent = (1 << 5),
|
||||
Incremental = (1 << 6),
|
||||
};
|
||||
|
||||
void set(unsigned int f, bool state = true) {
|
||||
|
@ -80,6 +81,10 @@ struct Analyzer {
|
|||
return get(Idempotent);
|
||||
}
|
||||
|
||||
bool isIncremental() const {
|
||||
return get(Incremental);
|
||||
}
|
||||
|
||||
bool matches() const {
|
||||
return get(Match);
|
||||
}
|
||||
|
|
|
@ -320,12 +320,14 @@ struct ForwardTraversal {
|
|||
Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&Analyzer::Action::isModified));
|
||||
const Token* nextStatement = Token::findmatch(writeTok, ";|}", endBlock);
|
||||
if (!Token::Match(nextStatement, ";|} break ;")) {
|
||||
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
||||
if (!allAnalysis.isIncremental())
|
||||
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
||||
return Break(Terminate::Bail);
|
||||
}
|
||||
} else {
|
||||
if (stepTok && updateRecursive(stepTok) == Progress::Break) {
|
||||
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
||||
if (!allAnalysis.isIncremental())
|
||||
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
||||
return Break(Terminate::Bail);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1893,13 +1893,14 @@ struct ValueFlowAnalyzer : Analyzer {
|
|||
} else {
|
||||
if (rhsValue && !value->isImpossible() && value->equalValue(*rhsValue))
|
||||
a = Action::Idempotent;
|
||||
a |= Action::Incremental;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// increment/decrement
|
||||
if (Token::Match(tok->previous(), "++|-- %name%") || Token::Match(tok, "%name% ++|--")) {
|
||||
return Action::Read | Action::Write;
|
||||
return Action::Read | Action::Write | Action::Incremental;
|
||||
}
|
||||
return Action::None;
|
||||
}
|
||||
|
@ -5706,17 +5707,17 @@ struct ContainerVariableAnalyzer : VariableAnalyzer {
|
|||
if (tok->valueType()->container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
|
||||
const Token* rhs = parent->astOperand2();
|
||||
if (rhs->tokType() == Token::eString)
|
||||
return Action::Read | Action::Write;
|
||||
return Action::Read | Action::Write | Action::Incremental;
|
||||
if (rhs->valueType() && rhs->valueType()->container && rhs->valueType()->container->stdStringLike) {
|
||||
if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) {
|
||||
return rhsval.isKnown() && rhsval.isContainerSizeValue();
|
||||
}))
|
||||
return Action::Read | Action::Write;
|
||||
return Action::Read | Action::Write | Action::Incremental;
|
||||
}
|
||||
} else if (Token::Match(tok, "%name% . %name% (")) {
|
||||
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP)
|
||||
return Action::Read | Action::Write;
|
||||
return Action::Read | Action::Write | Action::Incremental;
|
||||
}
|
||||
return Action::None;
|
||||
}
|
||||
|
|
|
@ -380,6 +380,22 @@ private:
|
|||
" return ArrS[0];\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkNormal("extern void Bar(const double, const double);\n"
|
||||
"void f(std::vector<double> &r, const double ) {\n"
|
||||
" std::vector<double> result;\n"
|
||||
" double d = 0.0;\n"
|
||||
" const double inc = 0.1;\n"
|
||||
" for(unsigned int i = 0; i < 10; ++i) {\n"
|
||||
" result.push_back(d);\n"
|
||||
" d = (i + 1) * inc;\n"
|
||||
" }\n"
|
||||
" Bar(1.0, d);\n"
|
||||
" Bar(10U, result.size());\n"
|
||||
" Bar(0.0, result[0]);\n"
|
||||
" Bar(0.34, result[1]);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void outOfBoundsIndexExpression() {
|
||||
|
|
Loading…
Reference in New Issue