diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 6249ccbfa..660735f6e 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1994,8 +1994,17 @@ const std::list & CheckClass::callsPureVirtualFunction(const Func if (found.second) { if (function.hasBody) { for (const Token *tok = function.arg->link(); - tok != function.functionScope->classEnd; + tok && tok != function.functionScope->classEnd; tok = tok->next()) { + if ((Token::simpleMatch(tok,") {") && + tok->link() && + Token::Match(tok->link()->previous(),"if|switch")) || + Token::simpleMatch(tok,"else {") + ) { + // Assume pure virtual function call is prevented by "if|else|switch" condition + tok = tok->linkAt(1); + continue; + } const Function * callFunction=tok->function(); if (!callFunction || function.nestedIn != callFunction->nestedIn || diff --git a/test/testclass.cpp b/test/testclass.cpp index a41bc73e3..0e5a21c22 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -176,6 +176,7 @@ private: TEST_CASE(pureVirtualFunctionCall); TEST_CASE(pureVirtualFunctionCallOtherClass); TEST_CASE(pureVirtualFunctionCallWithBody); + TEST_CASE(pureVirtualFunctionCallPrevented); TEST_CASE(duplInheritedMembers); } @@ -5731,6 +5732,45 @@ private: } + void pureVirtualFunctionCallPrevented() { + checkPureVirtualFunctionCall("class A\n" + " {\n" + " virtual void pure()=0;\n" + " void nonpure(bool bCallPure)\n" + " { if (bCallPure) pure();}\n" + " A(); \n" + "};\n" + "A::A()\n" + "{nonpure(false);}\n"); + ASSERT_EQUALS("", errout.str()); + + checkPureVirtualFunctionCall("class A\n" + " {\n" + " virtual void pure()=0;\n" + " void nonpure(bool bCallPure)\n" + " { if (!bCallPure) ; else pure();}\n" + " A(); \n" + "};\n" + "A::A()\n" + "{nonpure(false);}\n"); + ASSERT_EQUALS("", errout.str()); + + checkPureVirtualFunctionCall("class A\n" + " {\n" + " virtual void pure()=0;\n" + " void nonpure(bool bCallPure)\n" + " {\n" + " switch (bCallPure) {\n" + " case true: pure(); break;\n" + " }\n" + " }\n" + " A(); \n" + "};\n" + "A::A()\n" + "{nonpure(false);}\n"); + ASSERT_EQUALS("", errout.str()); + } + }; REGISTER_TEST(TestClass)