Skip to content

Commit da410bb

Browse files
authored
Fix #13326: FP shiftNegative for template argument (danmar#7045)
1 parent f7d0c25 commit da410bb

File tree

6 files changed

+119
-0
lines changed

6 files changed

+119
-0
lines changed

lib/astutils.cpp

+75
Original file line numberDiff line numberDiff line change
@@ -3797,3 +3797,78 @@ bool isUnreachableOperand(const Token *tok)
37973797

37983798
return false;
37993799
}
3800+
3801+
static bool unknownLeafValuesAreTemplateArgs(const Token *tok)
3802+
{
3803+
if (!tok)
3804+
return true;
3805+
3806+
if (!tok->astOperand1() && !tok->astOperand2())
3807+
return tok->isTemplateArg() || tok->hasKnownIntValue();
3808+
3809+
return unknownLeafValuesAreTemplateArgs(tok->astOperand1())
3810+
&& unknownLeafValuesAreTemplateArgs(tok->astOperand2());
3811+
}
3812+
3813+
static const Token *skipUnreachableIfBranch(const Token *tok)
3814+
{
3815+
const Token *condTok = tok->linkAt(-1);
3816+
if (!condTok)
3817+
return tok;
3818+
3819+
if (!Token::simpleMatch(condTok->tokAt(-1), "if") && !Token::simpleMatch(condTok->tokAt(-2), "if constexpr"))
3820+
return tok;
3821+
3822+
condTok = condTok->astOperand2();
3823+
if (!condTok)
3824+
return tok;
3825+
3826+
if ((condTok->hasKnownIntValue() && condTok->getKnownIntValue() == 0)
3827+
|| (unknownLeafValuesAreTemplateArgs(condTok) && condTok->getValue(0))) {
3828+
tok = tok->link();
3829+
}
3830+
3831+
return tok;
3832+
}
3833+
3834+
static const Token *skipUnreachableElseBranch(const Token *tok)
3835+
{
3836+
if (!Token::simpleMatch(tok->tokAt(-2), "} else {"))
3837+
return tok;
3838+
3839+
const Token *condTok = tok->linkAt(-2);
3840+
if (!condTok)
3841+
return tok;
3842+
3843+
condTok = condTok->linkAt(-1);
3844+
if (!condTok)
3845+
return tok;
3846+
3847+
if (!Token::simpleMatch(condTok->tokAt(-1), "if (") && !Token::simpleMatch(condTok->tokAt(-2), "if constexpr ("))
3848+
return tok;
3849+
3850+
condTok = condTok->astOperand2();
3851+
3852+
if ((condTok->hasKnownIntValue() && condTok->getKnownIntValue() != 0)
3853+
|| (unknownLeafValuesAreTemplateArgs(condTok) && condTok->getValueNE(0))) {
3854+
tok = tok->link();
3855+
}
3856+
3857+
return tok;
3858+
}
3859+
3860+
const Token *skipUnreachableBranch(const Token *tok)
3861+
{
3862+
if (!Token::simpleMatch(tok, "{"))
3863+
return tok;
3864+
3865+
if (tok->scope()->type == Scope::ScopeType::eIf) {
3866+
return skipUnreachableIfBranch(tok);
3867+
}
3868+
3869+
if (tok->scope()->type == Scope::ScopeType::eElse) {
3870+
return skipUnreachableElseBranch(tok);
3871+
}
3872+
3873+
return tok;
3874+
}

lib/astutils.h

+2
Original file line numberDiff line numberDiff line change
@@ -453,4 +453,6 @@ bool isExhaustiveSwitch(const Token *startbrace);
453453

454454
bool isUnreachableOperand(const Token *tok);
455455

456+
const Token *skipUnreachableBranch(const Token *tok);
457+
456458
#endif // astutilsH

lib/checkother.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -3114,6 +3114,8 @@ void CheckOther::checkNegativeBitwiseShift()
31143114
logChecker("CheckOther::checkNegativeBitwiseShift");
31153115

31163116
for (const Token* tok = mTokenizer->tokens(); tok; tok = tok->next()) {
3117+
tok = skipUnreachableBranch(tok);
3118+
31173119
if (!tok->astOperand1() || !tok->astOperand2())
31183120
continue;
31193121

lib/token.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,16 @@ const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Sett
18941894
});
18951895
}
18961896

1897+
const ValueFlow::Value * Token::getValueNE(MathLib::bigint val) const
1898+
{
1899+
if (!mImpl->mValues)
1900+
return nullptr;
1901+
const auto it = std::find_if(mImpl->mValues->cbegin(), mImpl->mValues->cend(), [=](const ValueFlow::Value& value) {
1902+
return value.isIntValue() && !value.isImpossible() && value.intvalue != val;
1903+
});
1904+
return it == mImpl->mValues->end() ? nullptr : &*it;
1905+
}
1906+
18971907
const ValueFlow::Value * Token::getInvalidValue(const Token *ftok, nonneg int argnr, const Settings &settings) const
18981908
{
18991909
if (!mImpl->mValues)

lib/token.h

+1
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,7 @@ class CPPCHECKLIB Token {
13001300

13011301
const ValueFlow::Value * getValueLE(MathLib::bigint val, const Settings &settings) const;
13021302
const ValueFlow::Value * getValueGE(MathLib::bigint val, const Settings &settings) const;
1303+
const ValueFlow::Value * getValueNE(MathLib::bigint val) const;
13031304

13041305
const ValueFlow::Value * getInvalidValue(const Token *ftok, nonneg int argnr, const Settings &settings) const;
13051306

test/testother.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -9369,6 +9369,35 @@ class TestOther : public TestFixture {
93699369
" }\n"
93709370
"}\n");
93719371
ASSERT_EQUALS("", errout_str());
9372+
9373+
// #13326
9374+
check("template<int b>\n"
9375+
"int f(int a)\n"
9376+
"{\n"
9377+
" if constexpr (b >= 0) {\n"
9378+
" return a << b;\n"
9379+
" } else {\n"
9380+
" return a << -b;\n"
9381+
" }\n"
9382+
"}\n"
9383+
"int g() {\n"
9384+
" return f<1>(2)\n"
9385+
"}\n");
9386+
ASSERT_EQUALS("", errout_str());
9387+
9388+
check("template<int b>\n"
9389+
"int f(int a)\n"
9390+
"{\n"
9391+
" if constexpr (b >= 0) {\n"
9392+
" return a << b;\n"
9393+
" } else {\n"
9394+
" return a << -b;\n"
9395+
" }\n"
9396+
"}\n"
9397+
"int g() {\n"
9398+
" return f<-1>(2)\n"
9399+
"}\n");
9400+
ASSERT_EQUALS("", errout_str());
93729401
}
93739402

93749403
void incompleteArrayFill() {

0 commit comments

Comments
 (0)