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),
|
Inconclusive = (1 << 3),
|
||||||
Match = (1 << 4),
|
Match = (1 << 4),
|
||||||
Idempotent = (1 << 5),
|
Idempotent = (1 << 5),
|
||||||
|
Incremental = (1 << 6),
|
||||||
};
|
};
|
||||||
|
|
||||||
void set(unsigned int f, bool state = true) {
|
void set(unsigned int f, bool state = true) {
|
||||||
|
@ -80,6 +81,10 @@ struct Analyzer {
|
||||||
return get(Idempotent);
|
return get(Idempotent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isIncremental() const {
|
||||||
|
return get(Incremental);
|
||||||
|
}
|
||||||
|
|
||||||
bool matches() const {
|
bool matches() const {
|
||||||
return get(Match);
|
return get(Match);
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,12 +320,14 @@ struct ForwardTraversal {
|
||||||
Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&Analyzer::Action::isModified));
|
Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&Analyzer::Action::isModified));
|
||||||
const Token* nextStatement = Token::findmatch(writeTok, ";|}", endBlock);
|
const Token* nextStatement = Token::findmatch(writeTok, ";|}", endBlock);
|
||||||
if (!Token::Match(nextStatement, ";|} break ;")) {
|
if (!Token::Match(nextStatement, ";|} break ;")) {
|
||||||
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
if (!allAnalysis.isIncremental())
|
||||||
|
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
||||||
return Break(Terminate::Bail);
|
return Break(Terminate::Bail);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (stepTok && updateRecursive(stepTok) == Progress::Break) {
|
if (stepTok && updateRecursive(stepTok) == Progress::Break) {
|
||||||
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
if (!allAnalysis.isIncremental())
|
||||||
|
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
|
||||||
return Break(Terminate::Bail);
|
return Break(Terminate::Bail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1893,13 +1893,14 @@ struct ValueFlowAnalyzer : Analyzer {
|
||||||
} else {
|
} else {
|
||||||
if (rhsValue && !value->isImpossible() && value->equalValue(*rhsValue))
|
if (rhsValue && !value->isImpossible() && value->equalValue(*rhsValue))
|
||||||
a = Action::Idempotent;
|
a = Action::Idempotent;
|
||||||
|
a |= Action::Incremental;
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment/decrement
|
// increment/decrement
|
||||||
if (Token::Match(tok->previous(), "++|-- %name%") || Token::Match(tok, "%name% ++|--")) {
|
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;
|
return Action::None;
|
||||||
}
|
}
|
||||||
|
@ -5706,17 +5707,17 @@ struct ContainerVariableAnalyzer : VariableAnalyzer {
|
||||||
if (tok->valueType()->container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
|
if (tok->valueType()->container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
|
||||||
const Token* rhs = parent->astOperand2();
|
const Token* rhs = parent->astOperand2();
|
||||||
if (rhs->tokType() == Token::eString)
|
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 (rhs->valueType() && rhs->valueType()->container && rhs->valueType()->container->stdStringLike) {
|
||||||
if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) {
|
if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) {
|
||||||
return rhsval.isKnown() && rhsval.isContainerSizeValue();
|
return rhsval.isKnown() && rhsval.isContainerSizeValue();
|
||||||
}))
|
}))
|
||||||
return Action::Read | Action::Write;
|
return Action::Read | Action::Write | Action::Incremental;
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok, "%name% . %name% (")) {
|
} else if (Token::Match(tok, "%name% . %name% (")) {
|
||||||
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||||
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP)
|
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;
|
return Action::None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,6 +380,22 @@ private:
|
||||||
" return ArrS[0];\n"
|
" return ArrS[0];\n"
|
||||||
"}\n", true);
|
"}\n", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void outOfBoundsIndexExpression() {
|
||||||
|
|
Loading…
Reference in New Issue