parent
ccd525962b
commit
1ec7397c21
|
@ -725,8 +725,7 @@ void execute(const Token* expr,
|
||||||
*result = 0;
|
*result = 0;
|
||||||
else
|
else
|
||||||
*error = true;
|
*error = true;
|
||||||
}
|
} else if (expr->str() == "(" && expr->isCast()) {
|
||||||
else if (expr->str() == "(" && expr->isCast()) {
|
|
||||||
if (Token::simpleMatch(expr->previous(), ">") && expr->previous()->link())
|
if (Token::simpleMatch(expr->previous(), ">") && expr->previous()->link())
|
||||||
execute(expr->astOperand2(), programMemory, result, error);
|
execute(expr->astOperand2(), programMemory, result, error);
|
||||||
else
|
else
|
||||||
|
|
|
@ -2590,10 +2590,10 @@ static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
static Analyzer::Result valueFlowForward(Token* top,
|
static Analyzer::Result valueFlowForward(Token* top,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* const tokenlist,
|
TokenList* const tokenlist,
|
||||||
const Settings* settings)
|
const Settings* settings)
|
||||||
{
|
{
|
||||||
Analyzer::Result result{};
|
Analyzer::Result result{};
|
||||||
for (const ValueFlow::Value& v : values) {
|
for (const ValueFlow::Value& v : values) {
|
||||||
|
@ -4040,13 +4040,13 @@ static void valueFlowSymbolic(TokenList* tokenlist, SymbolDatabase* symboldataba
|
||||||
ValueFlow::Value rhs = makeSymbolic(tok->astOperand2());
|
ValueFlow::Value rhs = makeSymbolic(tok->astOperand2());
|
||||||
rhs.errorPath.emplace_back(tok,
|
rhs.errorPath.emplace_back(tok,
|
||||||
tok->astOperand1()->expressionString() + " is assigned '" +
|
tok->astOperand1()->expressionString() + " is assigned '" +
|
||||||
tok->astOperand2()->expressionString() + "' here.");
|
tok->astOperand2()->expressionString() + "' here.");
|
||||||
valueFlowForward(start, end, tok->astOperand1(), {rhs}, tokenlist, tokenlist->getSettings());
|
valueFlowForward(start, end, tok->astOperand1(), {rhs}, tokenlist, tokenlist->getSettings());
|
||||||
|
|
||||||
ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
|
ValueFlow::Value lhs = makeSymbolic(tok->astOperand1());
|
||||||
lhs.errorPath.emplace_back(tok,
|
lhs.errorPath.emplace_back(tok,
|
||||||
tok->astOperand1()->expressionString() + " is assigned '" +
|
tok->astOperand1()->expressionString() + " is assigned '" +
|
||||||
tok->astOperand2()->expressionString() + "' here.");
|
tok->astOperand2()->expressionString() + "' here.");
|
||||||
valueFlowForward(start, end, tok->astOperand2(), {lhs}, tokenlist, tokenlist->getSettings());
|
valueFlowForward(start, end, tok->astOperand2(), {lhs}, tokenlist, tokenlist->getSettings());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4071,16 +4071,16 @@ static void valueFlowSymbolicInfer(TokenList* tokenlist, SymbolDatabase* symbold
|
||||||
|
|
||||||
MathLib::bigint rhsvalue = 0;
|
MathLib::bigint rhsvalue = 0;
|
||||||
const ValueFlow::Value* rhs =
|
const ValueFlow::Value* rhs =
|
||||||
ValueFlow::findValue(tok->astOperand2()->values(), nullptr, [&](const ValueFlow::Value& v) {
|
ValueFlow::findValue(tok->astOperand2()->values(), nullptr, [&](const ValueFlow::Value& v) {
|
||||||
return v.isSymbolicValue() && v.tokvalue && v.tokvalue->exprId() == tok->astOperand1()->exprId();
|
return v.isSymbolicValue() && v.tokvalue && v.tokvalue->exprId() == tok->astOperand1()->exprId();
|
||||||
});
|
});
|
||||||
if (rhs)
|
if (rhs)
|
||||||
rhsvalue = rhs->intvalue;
|
rhsvalue = rhs->intvalue;
|
||||||
MathLib::bigint lhsvalue = 0;
|
MathLib::bigint lhsvalue = 0;
|
||||||
const ValueFlow::Value* lhs =
|
const ValueFlow::Value* lhs =
|
||||||
ValueFlow::findValue(tok->astOperand1()->values(), nullptr, [&](const ValueFlow::Value& v) {
|
ValueFlow::findValue(tok->astOperand1()->values(), nullptr, [&](const ValueFlow::Value& v) {
|
||||||
return v.isSymbolicValue() && v.tokvalue && v.tokvalue->exprId() == tok->astOperand2()->exprId();
|
return v.isSymbolicValue() && v.tokvalue && v.tokvalue->exprId() == tok->astOperand2()->exprId();
|
||||||
});
|
});
|
||||||
if (lhs)
|
if (lhs)
|
||||||
lhsvalue = lhs->intvalue;
|
lhsvalue = lhs->intvalue;
|
||||||
if (!lhs && !rhs)
|
if (!lhs && !rhs)
|
||||||
|
@ -4607,10 +4607,12 @@ struct ConditionHandler {
|
||||||
changePossibleToKnown(values);
|
changePossibleToKnown(values);
|
||||||
if (astIsFloat(cond.vartok, false) ||
|
if (astIsFloat(cond.vartok, false) ||
|
||||||
(!cond.vartok->valueType() &&
|
(!cond.vartok->valueType() &&
|
||||||
std::all_of(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
std::all_of(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
||||||
return v.isIntValue() || v.isFloatValue();
|
return v.isIntValue() || v.isFloatValue();
|
||||||
})))
|
})))
|
||||||
values.remove_if([&](const ValueFlow::Value& v) { return v.isImpossible(); });
|
values.remove_if([&](const ValueFlow::Value& v) {
|
||||||
|
return v.isImpossible();
|
||||||
|
});
|
||||||
Analyzer::Result r = forward(parent->astOperand2(), cond.vartok, values, tokenlist, settings);
|
Analyzer::Result r = forward(parent->astOperand2(), cond.vartok, values, tokenlist, settings);
|
||||||
if (r.terminate != Analyzer::Terminate::None)
|
if (r.terminate != Analyzer::Terminate::None)
|
||||||
return;
|
return;
|
||||||
|
@ -4807,8 +4809,7 @@ struct SimpleConditionHandler : ConditionHandler {
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* tokenlist,
|
TokenList* tokenlist,
|
||||||
const Settings* settings) const OVERRIDE
|
const Settings* settings) const OVERRIDE {
|
||||||
{
|
|
||||||
return valueFlowForward(top, exprTok, values, tokenlist, settings);
|
return valueFlowForward(top, exprTok, values, tokenlist, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4821,8 +4822,7 @@ struct SimpleConditionHandler : ConditionHandler {
|
||||||
return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings);
|
return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE
|
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE {
|
||||||
{
|
|
||||||
Condition cond;
|
Condition cond;
|
||||||
ValueFlow::Value true_value;
|
ValueFlow::Value true_value;
|
||||||
ValueFlow::Value false_value;
|
ValueFlow::Value false_value;
|
||||||
|
@ -6172,9 +6172,9 @@ static Analyzer::Result valueFlowContainerForward(Token* startToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
static Analyzer::Result valueFlowContainerForwardRecursive(Token* top,
|
static Analyzer::Result valueFlowContainerForwardRecursive(Token* top,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const ValueFlow::Value& value,
|
const ValueFlow::Value& value,
|
||||||
TokenList* tokenlist)
|
TokenList* tokenlist)
|
||||||
{
|
{
|
||||||
ContainerExpressionAnalyzer a(exprTok, value, tokenlist);
|
ContainerExpressionAnalyzer a(exprTok, value, tokenlist);
|
||||||
return valueFlowGenericForward(top, a, tokenlist->getSettings());
|
return valueFlowGenericForward(top, a, tokenlist->getSettings());
|
||||||
|
@ -6355,8 +6355,7 @@ static std::list<ValueFlow::Value> getIteratorValues(std::list<ValueFlow::Value>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IteratorConditionHandler : SimpleConditionHandler {
|
struct IteratorConditionHandler : SimpleConditionHandler {
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE
|
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE {
|
||||||
{
|
|
||||||
Condition cond;
|
Condition cond;
|
||||||
|
|
||||||
ValueFlow::Value true_value;
|
ValueFlow::Value true_value;
|
||||||
|
@ -6567,8 +6566,7 @@ struct ContainerConditionHandler : ConditionHandler {
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
const std::list<ValueFlow::Value>& values,
|
const std::list<ValueFlow::Value>& values,
|
||||||
TokenList* tokenlist,
|
TokenList* tokenlist,
|
||||||
const Settings*) const OVERRIDE
|
const Settings*) const OVERRIDE {
|
||||||
{
|
|
||||||
Analyzer::Result result{};
|
Analyzer::Result result{};
|
||||||
for (const ValueFlow::Value& value : values)
|
for (const ValueFlow::Value& value : values)
|
||||||
result.update(valueFlowContainerForwardRecursive(top, exprTok, value, tokenlist));
|
result.update(valueFlowContainerForwardRecursive(top, exprTok, value, tokenlist));
|
||||||
|
@ -6584,8 +6582,7 @@ struct ContainerConditionHandler : ConditionHandler {
|
||||||
return valueFlowContainerReverse(start, endTok, exprTok, values, tokenlist, settings);
|
return valueFlowContainerReverse(start, endTok, exprTok, values, tokenlist, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE
|
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE {
|
||||||
{
|
|
||||||
Condition cond;
|
Condition cond;
|
||||||
ValueFlow::Value true_value;
|
ValueFlow::Value true_value;
|
||||||
ValueFlow::Value false_value;
|
ValueFlow::Value false_value;
|
||||||
|
|
|
@ -286,7 +286,9 @@ namespace ValueFlow {
|
||||||
bool isIteratorEndValue() const {
|
bool isIteratorEndValue() const {
|
||||||
return valueType == ValueType::ITERATOR_END;
|
return valueType == ValueType::ITERATOR_END;
|
||||||
}
|
}
|
||||||
bool isSymbolicValue() const { return valueType == ValueType::SYMBOLIC; }
|
bool isSymbolicValue() const {
|
||||||
|
return valueType == ValueType::SYMBOLIC;
|
||||||
|
}
|
||||||
|
|
||||||
bool isLocalLifetimeValue() const {
|
bool isLocalLifetimeValue() const {
|
||||||
return valueType == ValueType::LIFETIME && lifetimeScope == LifetimeScope::Local;
|
return valueType == ValueType::LIFETIME && lifetimeScope == LifetimeScope::Local;
|
||||||
|
|
|
@ -255,7 +255,7 @@ private:
|
||||||
TEST_CASE(sameExpressionPointers);
|
TEST_CASE(sameExpressionPointers);
|
||||||
|
|
||||||
TEST_CASE(checkOverlappingWrite);
|
TEST_CASE(checkOverlappingWrite);
|
||||||
|
|
||||||
TEST_CASE(constVariableArrayMember); // #10371
|
TEST_CASE(constVariableArrayMember); // #10371
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9491,7 +9491,7 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Overlapping read/write in strcpy() is undefined behavior\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (error) Overlapping read/write in strcpy() is undefined behavior\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void constVariableArrayMember() { // #10371
|
void constVariableArrayMember() { // #10371
|
||||||
check("class Foo {\n"
|
check("class Foo {\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
|
|
|
@ -1419,8 +1419,7 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void iterator27()
|
void iterator27() {
|
||||||
{
|
|
||||||
// #10378
|
// #10378
|
||||||
check("struct A {\n"
|
check("struct A {\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
|
|
|
@ -154,7 +154,9 @@ private:
|
||||||
return !val.isLifetimeValue();
|
return !val.isLifetimeValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isNotUninitValue(const ValueFlow::Value& val) { return !val.isUninitValue(); }
|
static bool isNotUninitValue(const ValueFlow::Value& val) {
|
||||||
|
return !val.isUninitValue();
|
||||||
|
}
|
||||||
|
|
||||||
static bool isNotPossible(const ValueFlow::Value& val) {
|
static bool isNotPossible(const ValueFlow::Value& val) {
|
||||||
return !val.isPossible();
|
return !val.isPossible();
|
||||||
|
|
Loading…
Reference in New Issue