Fixed #1883 (false positive: (style) The function 'A::SetPos' can be const)
This commit is contained in:
parent
d4d0bc050a
commit
4cf92992a8
|
@ -1992,7 +1992,7 @@ void CheckClass::checkConst()
|
|||
}
|
||||
|
||||
// if nothing non-const was found. write error..
|
||||
if (checkConstFunc(classname, varlist, paramEnd))
|
||||
if (checkConstFunc(info.className, info.derivedFrom, varlist, paramEnd))
|
||||
{
|
||||
for (int i = nestInfo.size() - 2; i >= 0; i--)
|
||||
classname = std::string(nestInfo[i].className + "::" + classname);
|
||||
|
@ -2027,7 +2027,7 @@ void CheckClass::checkConst()
|
|||
if (sameFunc(namespaceLevel, tok2, paramEnd))
|
||||
{
|
||||
// if nothing non-const was found. write error..
|
||||
if (checkConstFunc(classname, varlist, paramEnd))
|
||||
if (checkConstFunc(info.className, info.derivedFrom, varlist, paramEnd))
|
||||
{
|
||||
for (int k = nestInfo.size() - 2; k >= 0; k--)
|
||||
classname = std::string(nestInfo[k].className + "::" + classname);
|
||||
|
@ -2254,7 +2254,7 @@ bool CheckClass::isMemberFunc(const Token *tok)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CheckClass::isMemberVar(const std::string &classname, const Var *varlist, const Token *tok)
|
||||
bool CheckClass::isMemberVar(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok)
|
||||
{
|
||||
while (tok->previous() && !Token::Match(tok->previous(), "}|{|;|public:|protected:|private:|return|:|?"))
|
||||
{
|
||||
|
@ -2282,10 +2282,71 @@ bool CheckClass::isMemberVar(const std::string &classname, const Var *varlist, c
|
|||
}
|
||||
}
|
||||
|
||||
// not found in this class
|
||||
if (!derivedFrom.empty())
|
||||
{
|
||||
// check each base class
|
||||
for (unsigned int i = 0; i < derivedFrom.size(); ++i)
|
||||
{
|
||||
std::string className;
|
||||
|
||||
if (derivedFrom[i].find("::") != std::string::npos)
|
||||
{
|
||||
/** @todo handle nested base classes and namespaces */
|
||||
}
|
||||
else
|
||||
className = derivedFrom[i];
|
||||
|
||||
std::string classPattern = std::string("class|struct ") + className + std::string(" {|:");
|
||||
|
||||
// find the base class
|
||||
const Token *classToken = Token::findmatch(_tokenizer->tokens(), classPattern.c_str());
|
||||
|
||||
// find the function in the base class
|
||||
if (classToken)
|
||||
{
|
||||
std::vector<std::string> baseList;
|
||||
const Token * tok1 = classToken;
|
||||
|
||||
while (tok1->str() != "{")
|
||||
{
|
||||
// check for base classes
|
||||
if (Token::Match(tok1, ":|, public|protected|private"))
|
||||
{
|
||||
// jump to base class name
|
||||
tok1 = tok1->tokAt(2);
|
||||
|
||||
std::string base;
|
||||
|
||||
// handle nested base classea and namespacess
|
||||
while (Token::Match(tok1, "%var% ::"))
|
||||
{
|
||||
base += tok1->str();
|
||||
base += " :: ";
|
||||
tok1 = tok1->tokAt(2);
|
||||
}
|
||||
|
||||
base += tok1->str();
|
||||
|
||||
// save pattern for base class name
|
||||
baseList.push_back(base);
|
||||
}
|
||||
tok1 = tok1->next();
|
||||
}
|
||||
|
||||
// Get class variables...
|
||||
Var *varlist1 = getVarList(classToken);
|
||||
|
||||
if (isMemberVar(classToken->next()->str(), baseList, varlist1, tok))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckClass::checkConstFunc(const std::string &classname, const Var *varlist, const Token *tok)
|
||||
bool CheckClass::checkConstFunc(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok)
|
||||
{
|
||||
// if the function doesn't have any assignment nor function call,
|
||||
// it can be a const function..
|
||||
|
@ -2307,7 +2368,7 @@ bool CheckClass::checkConstFunc(const std::string &classname, const Var *varlist
|
|||
(tok1->str().find("=") == 1 &&
|
||||
tok1->str().find_first_of("<!>") == std::string::npos))
|
||||
{
|
||||
if (isMemberVar(classname, varlist, tok1->previous()))
|
||||
if (isMemberVar(classname, derivedFrom, varlist, tok1->previous()))
|
||||
{
|
||||
isconst = false;
|
||||
break;
|
||||
|
@ -2315,7 +2376,7 @@ bool CheckClass::checkConstFunc(const std::string &classname, const Var *varlist
|
|||
}
|
||||
|
||||
// streaming: <<
|
||||
else if (tok1->str() == "<<" && isMemberVar(classname, varlist, tok1->previous()))
|
||||
else if (tok1->str() == "<<" && isMemberVar(classname, derivedFrom, varlist, tok1->previous()))
|
||||
{
|
||||
isconst = false;
|
||||
break;
|
||||
|
|
|
@ -165,8 +165,8 @@ private:
|
|||
|
||||
bool sameFunc(int nest, const Token *firstEnd, const Token *secondEnd);
|
||||
bool isMemberFunc(const Token *tok);
|
||||
bool isMemberVar(const std::string &classname, const Var *varlist, const Token *tok);
|
||||
bool checkConstFunc(const std::string &classname, const Var *varlist, const Token *tok);
|
||||
bool isMemberVar(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
||||
bool checkConstFunc(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
||||
|
||||
/** @brief check if this function is virtual in the base classes */
|
||||
bool isVirtual(const std::vector<std::string> &derivedFrom, const Token *functionToken) const;
|
||||
|
|
|
@ -130,6 +130,7 @@ private:
|
|||
TEST_CASE(const25); // ticket #1724
|
||||
TEST_CASE(const26); // ticket #1847
|
||||
TEST_CASE(const27); // ticket #1882
|
||||
TEST_CASE(const28); // ticket #1883
|
||||
TEST_CASE(constoperator1); // operator< can often be const
|
||||
TEST_CASE(constoperator2); // operator<<
|
||||
TEST_CASE(constincdec); // increment/decrement => non-const
|
||||
|
@ -3612,6 +3613,25 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void const28() // ticket #1883
|
||||
{
|
||||
checkConst("class P {\n"
|
||||
"public:\n"
|
||||
" P() { x=0.0; y=0.0; }\n"
|
||||
" double x,y;\n"
|
||||
"};\n"
|
||||
"class A : public P {\n"
|
||||
"public:\n"
|
||||
" A():P(){}\n"
|
||||
" void SetPos(double xPos, double yPos) {\n"
|
||||
" x=xPos;\n"
|
||||
" y=yPos;\n"
|
||||
" }\n"
|
||||
"};\n"
|
||||
);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void const27() // ticket #1882
|
||||
{
|
||||
checkConst("class A {\n"
|
||||
|
|
Loading…
Reference in New Issue