Skip to content

Commit b3382da

Browse files
committed
Handle impossible values
1 parent bebcdcd commit b3382da

2 files changed

Lines changed: 74 additions & 44 deletions

File tree

‎lib/valueflow.cpp‎

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,53 +1145,76 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& sett
11451145
value.setImpossible();
11461146
setTokenValue(tok, std::move(value), settings);
11471147
} else if (tok->isBinaryOp() && tok->str() == "|") {
1148-
const ValueFlow::Value* opVal = tok->astOperand1()->getKnownValue(ValueFlow::Value::ValueType::INT);
1149-
if (!opVal)
1150-
opVal = tok->astOperand2()->getKnownValue(ValueFlow::Value::ValueType::INT);
1151-
if (opVal && opVal->intvalue != 0) {
1148+
bool nonNull = false;
1149+
for (const Token *op : {tok->astOperand1(), tok->astOperand2()}) {
1150+
for (const ValueFlow::Value& v : op->values()) {
1151+
if (v.valueType != ValueFlow::Value::ValueType::INT)
1152+
continue;
1153+
if ((v.isKnown() && v.intvalue != 0) || (v.isImpossible() && v.intvalue == 0)) {
1154+
nonNull = true;
1155+
break;
1156+
}
1157+
}
1158+
if (nonNull)
1159+
break;
1160+
}
1161+
if (nonNull) {
1162+
ValueFlow::Value value{0};
1163+
value.setImpossible();
1164+
setTokenValue(tok, std::move(value), settings);
1165+
}
1166+
} else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl ("))
1167+
{
1168+
ValueFlow::Value value{-1};
1169+
value.bound = ValueFlow::Value::Bound::Upper;
1170+
value.setImpossible();
1171+
setTokenValue(tok->next(), std::move(value), settings);
1172+
}
1173+
else if (Token::Match(tok, ". data|c_str (") && astIsContainerOwned(tok->astOperand1()))
1174+
{
1175+
const Library::Container *container = getLibraryContainer(tok->astOperand1());
1176+
if (!container)
1177+
continue;
1178+
if (!container->stdStringLike)
1179+
continue;
1180+
if (container->view)
1181+
continue;
1182+
ValueFlow::Value value{0};
1183+
value.setImpossible();
1184+
setTokenValue(tok->tokAt(2), std::move(value), settings);
1185+
}
1186+
else if (Token::Match(tok, "make_shared|make_unique <") && Token::simpleMatch(tok->linkAt(1), "> ("))
1187+
{
1188+
ValueFlow::Value value{0};
1189+
value.setImpossible();
1190+
setTokenValue(tok->linkAt(1)->next(), std::move(value), settings);
1191+
}
1192+
else if ((tokenList.isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&"))
1193+
{
1194+
ValueFlow::Value value{0};
1195+
value.setImpossible();
1196+
setTokenValue(tok, std::move(value), settings);
1197+
}
1198+
else if (tok->variable() && tok->variable()->isArray() && !tok->variable()->isArgument() &&
1199+
tok->variable()->getTypeName() != "std::array")
1200+
{
1201+
ValueFlow::Value value{0};
1202+
value.setImpossible();
1203+
setTokenValue(tok, std::move(value), settings);
1204+
}
1205+
else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") &&
1206+
isConvertedToIntegral(tok->astParent(), settings))
1207+
{
1208+
ValueFlow::Value value{0};
1209+
value.setImpossible();
1210+
setTokenValue(tok, std::move(value), settings);
1211+
}
1212+
else if (tok->function() && tok->scope()->isExecutable())
1213+
{
11521214
ValueFlow::Value value{0};
11531215
value.setImpossible();
11541216
setTokenValue(tok, std::move(value), settings);
11551217
}
1156-
} else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) {
1157-
ValueFlow::Value value{-1};
1158-
value.bound = ValueFlow::Value::Bound::Upper;
1159-
value.setImpossible();
1160-
setTokenValue(tok->next(), std::move(value), settings);
1161-
} else if (Token::Match(tok, ". data|c_str (") && astIsContainerOwned(tok->astOperand1())) {
1162-
const Library::Container* container = getLibraryContainer(tok->astOperand1());
1163-
if (!container)
1164-
continue;
1165-
if (!container->stdStringLike)
1166-
continue;
1167-
if (container->view)
1168-
continue;
1169-
ValueFlow::Value value{0};
1170-
value.setImpossible();
1171-
setTokenValue(tok->tokAt(2), std::move(value), settings);
1172-
} else if (Token::Match(tok, "make_shared|make_unique <") && Token::simpleMatch(tok->linkAt(1), "> (")) {
1173-
ValueFlow::Value value{0};
1174-
value.setImpossible();
1175-
setTokenValue(tok->linkAt(1)->next(), std::move(value), settings);
1176-
} else if ((tokenList.isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&")) {
1177-
ValueFlow::Value value{0};
1178-
value.setImpossible();
1179-
setTokenValue(tok, std::move(value), settings);
1180-
} else if (tok->variable() && tok->variable()->isArray() && !tok->variable()->isArgument() &&
1181-
tok->variable()->getTypeName() != "std::array") {
1182-
ValueFlow::Value value{0};
1183-
value.setImpossible();
1184-
setTokenValue(tok, std::move(value), settings);
1185-
} else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") &&
1186-
isConvertedToIntegral(tok->astParent(), settings)) {
1187-
ValueFlow::Value value{0};
1188-
value.setImpossible();
1189-
setTokenValue(tok, std::move(value), settings);
1190-
} else if (tok->function() && tok->scope()->isExecutable()) {
1191-
ValueFlow::Value value{0};
1192-
value.setImpossible();
1193-
setTokenValue(tok, std::move(value), settings);
1194-
}
11951218
}
11961219
}
11971220

‎test/testcondition.cpp‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5003,8 +5003,15 @@ class TestCondition : public TestFixture {
50035003
check("void f(int i) {\n" // #15144
50045004
" int c = i | 1;\n"
50055005
" if (c) {}\n"
5006+
"}\n"
5007+
"void g(int i, int m) {\n"
5008+
" if (m == 0)\n"
5009+
" return;\n"
5010+
" int c = i | m;\n"
5011+
" if (c) {}\n"
50065012
"}\n");
5007-
ASSERT_EQUALS("[test.cpp:3:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n",
5013+
ASSERT_EQUALS("[test.cpp:3:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n"
5014+
"[test.cpp:9:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n",
50085015
errout_str());
50095016
}
50105017

0 commit comments

Comments
 (0)