Skip to content

Commit 445d08d

Browse files
committed
Fixed cppcheck-opensource#4723 (False positive: Pure virtual call within conditional clause)
1 parent 44d86e9 commit 445d08d

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

lib/checkclass.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1994,8 +1994,17 @@ const std::list<const Token *> & CheckClass::callsPureVirtualFunction(const Func
19941994
if (found.second) {
19951995
if (function.hasBody) {
19961996
for (const Token *tok = function.arg->link();
1997-
tok != function.functionScope->classEnd;
1997+
tok && tok != function.functionScope->classEnd;
19981998
tok = tok->next()) {
1999+
if ((Token::simpleMatch(tok,") {") &&
2000+
tok->link() &&
2001+
Token::Match(tok->link()->previous(),"if|switch")) ||
2002+
Token::simpleMatch(tok,"else {")
2003+
) {
2004+
// Assume pure virtual function call is prevented by "if|else|switch" condition
2005+
tok = tok->linkAt(1);
2006+
continue;
2007+
}
19992008
const Function * callFunction=tok->function();
20002009
if (!callFunction ||
20012010
function.nestedIn != callFunction->nestedIn ||

test/testclass.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class TestClass : public TestFixture {
176176
TEST_CASE(pureVirtualFunctionCall);
177177
TEST_CASE(pureVirtualFunctionCallOtherClass);
178178
TEST_CASE(pureVirtualFunctionCallWithBody);
179+
TEST_CASE(pureVirtualFunctionCallPrevented);
179180

180181
TEST_CASE(duplInheritedMembers);
181182
}
@@ -5731,6 +5732,45 @@ class TestClass : public TestFixture {
57315732

57325733
}
57335734

5735+
void pureVirtualFunctionCallPrevented() {
5736+
checkPureVirtualFunctionCall("class A\n"
5737+
" {\n"
5738+
" virtual void pure()=0;\n"
5739+
" void nonpure(bool bCallPure)\n"
5740+
" { if (bCallPure) pure();}\n"
5741+
" A(); \n"
5742+
"};\n"
5743+
"A::A()\n"
5744+
"{nonpure(false);}\n");
5745+
ASSERT_EQUALS("", errout.str());
5746+
5747+
checkPureVirtualFunctionCall("class A\n"
5748+
" {\n"
5749+
" virtual void pure()=0;\n"
5750+
" void nonpure(bool bCallPure)\n"
5751+
" { if (!bCallPure) ; else pure();}\n"
5752+
" A(); \n"
5753+
"};\n"
5754+
"A::A()\n"
5755+
"{nonpure(false);}\n");
5756+
ASSERT_EQUALS("", errout.str());
5757+
5758+
checkPureVirtualFunctionCall("class A\n"
5759+
" {\n"
5760+
" virtual void pure()=0;\n"
5761+
" void nonpure(bool bCallPure)\n"
5762+
" {\n"
5763+
" switch (bCallPure) {\n"
5764+
" case true: pure(); break;\n"
5765+
" }\n"
5766+
" }\n"
5767+
" A(); \n"
5768+
"};\n"
5769+
"A::A()\n"
5770+
"{nonpure(false);}\n");
5771+
ASSERT_EQUALS("", errout.str());
5772+
}
5773+
57345774
};
57355775

57365776
REGISTER_TEST(TestClass)

0 commit comments

Comments
 (0)