Merge branch 'master' of github.com:danmar/cppcheck
This commit is contained in:
commit
df1c911d84
|
@ -1992,7 +1992,7 @@ void CheckClass::checkConst()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if nothing non-const was found. write error..
|
// 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--)
|
for (int i = nestInfo.size() - 2; i >= 0; i--)
|
||||||
classname = std::string(nestInfo[i].className + "::" + classname);
|
classname = std::string(nestInfo[i].className + "::" + classname);
|
||||||
|
@ -2027,7 +2027,7 @@ void CheckClass::checkConst()
|
||||||
if (sameFunc(namespaceLevel, tok2, paramEnd))
|
if (sameFunc(namespaceLevel, tok2, paramEnd))
|
||||||
{
|
{
|
||||||
// if nothing non-const was found. write error..
|
// 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--)
|
for (int k = nestInfo.size() - 2; k >= 0; k--)
|
||||||
classname = std::string(nestInfo[k].className + "::" + classname);
|
classname = std::string(nestInfo[k].className + "::" + classname);
|
||||||
|
@ -2254,7 +2254,7 @@ bool CheckClass::isMemberFunc(const Token *tok)
|
||||||
return false;
|
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|:|?"))
|
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;
|
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,
|
// if the function doesn't have any assignment nor function call,
|
||||||
// it can be a const function..
|
// 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("=") == 1 &&
|
||||||
tok1->str().find_first_of("<!>") == std::string::npos))
|
tok1->str().find_first_of("<!>") == std::string::npos))
|
||||||
{
|
{
|
||||||
if (isMemberVar(classname, varlist, tok1->previous()))
|
if (isMemberVar(classname, derivedFrom, varlist, tok1->previous()))
|
||||||
{
|
{
|
||||||
isconst = false;
|
isconst = false;
|
||||||
break;
|
break;
|
||||||
|
@ -2315,7 +2376,7 @@ bool CheckClass::checkConstFunc(const std::string &classname, const Var *varlist
|
||||||
}
|
}
|
||||||
|
|
||||||
// streaming: <<
|
// streaming: <<
|
||||||
else if (tok1->str() == "<<" && isMemberVar(classname, varlist, tok1->previous()))
|
else if (tok1->str() == "<<" && isMemberVar(classname, derivedFrom, varlist, tok1->previous()))
|
||||||
{
|
{
|
||||||
isconst = false;
|
isconst = false;
|
||||||
break;
|
break;
|
||||||
|
@ -2329,7 +2390,7 @@ bool CheckClass::checkConstFunc(const std::string &classname, const Var *varlist
|
||||||
}
|
}
|
||||||
|
|
||||||
// function call..
|
// function call..
|
||||||
else if ((tok1->str() != "return" && Token::Match(tok1, "%var% (") && tok1->str() != "c_str") ||
|
else if ((Token::Match(tok1, "%var% (") && !Token::Match(tok1, "return|c_str|if")) ||
|
||||||
Token::Match(tok1, "%var% < %any% > ("))
|
Token::Match(tok1, "%var% < %any% > ("))
|
||||||
{
|
{
|
||||||
isconst = false;
|
isconst = false;
|
||||||
|
|
|
@ -165,8 +165,8 @@ private:
|
||||||
|
|
||||||
bool sameFunc(int nest, const Token *firstEnd, const Token *secondEnd);
|
bool sameFunc(int nest, const Token *firstEnd, const Token *secondEnd);
|
||||||
bool isMemberFunc(const Token *tok);
|
bool isMemberFunc(const Token *tok);
|
||||||
bool isMemberVar(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 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 */
|
/** @brief check if this function is virtual in the base classes */
|
||||||
bool isVirtual(const std::vector<std::string> &derivedFrom, const Token *functionToken) const;
|
bool isVirtual(const std::vector<std::string> &derivedFrom, const Token *functionToken) const;
|
||||||
|
|
|
@ -3395,6 +3395,22 @@ private:
|
||||||
// it is possible that the variable is initialized here
|
// it is possible that the variable is initialized here
|
||||||
if (Token::Match(tok2->previous(), "[(,] %var% [,)]"))
|
if (Token::Match(tok2->previous(), "[(,] %var% [,)]"))
|
||||||
bailouts.insert(tok2->varId());
|
bailouts.insert(tok2->varId());
|
||||||
|
|
||||||
|
// array initialization..
|
||||||
|
if (Token::Match(tok2->previous(), "[,(] %var% +"))
|
||||||
|
{
|
||||||
|
// if var is array, bailout
|
||||||
|
for (std::list<ExecutionPath *>::const_iterator it = checks.begin(); it != checks.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->varId == tok2->varId())
|
||||||
|
{
|
||||||
|
const CheckUninitVar *c = dynamic_cast<const CheckUninitVar *>(*it);
|
||||||
|
if (c && c->array)
|
||||||
|
bailouts.insert(tok2->varId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3945,7 +3961,11 @@ void CheckOther::charBitOpError(const Token *tok)
|
||||||
|
|
||||||
void CheckOther::variableScopeError(const Token *tok, const std::string &varname)
|
void CheckOther::variableScopeError(const Token *tok, const std::string &varname)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::style, "variableScope", "The scope of the variable " + varname + " can be reduced");
|
reportError(tok,
|
||||||
|
Severity::style,
|
||||||
|
"variableScope",
|
||||||
|
"The scope of the variable " + varname + " can be reduced\n"
|
||||||
|
"Be very careful when you reduce the scope! The logical behaviour can be changed by mistake, for example when reducing the scope in a loop.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckOther::conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse)
|
void CheckOther::conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse)
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY MACHINE, SEE ../tools/errmsg.cpp !
|
|
||||||
|
|
||||||
#ifndef errorloggerH
|
#ifndef errorloggerH
|
||||||
#define errorloggerH
|
#define errorloggerH
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -153,189 +153,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void reportStatus(unsigned int index, unsigned int max) = 0;
|
virtual void reportStatus(unsigned int index, unsigned int max) = 0;
|
||||||
|
|
||||||
static bool outOfBounds()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool stlOutOfBounds()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool noConstructor(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool uninitVar(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool unusedPrivateFunction(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool memsetClass()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool memsetStruct()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool operatorEq(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool virtualDestructor()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool mismatchAllocDealloc()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool memleak()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool resourceLeak()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool deallocDealloc()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool deallocuse()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool mismatchSize()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool cstyleCast(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool redundantIfDelete0(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool redundantIfRemove(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool dangerousUsageStrtol()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ifNoAction(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool sprintfOverlappingData()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool udivError()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool unusedStructMember(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool passedByValue(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool constStatement(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool charArrayIndex(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool charBitOp(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool variableScope()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool conditionAlwaysTrueFalse(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool strPlusChar()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool returnLocalVariable()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool dangerousFunctionmktemp(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool dangerousFunctiongets(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool dangerousFunctionscanf(const Settings &s)
|
|
||||||
{
|
|
||||||
return s._checkCodingStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack);
|
static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5735,8 +5735,9 @@ bool Tokenizer::simplifyRedundantParanthesis()
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Token::simpleMatch(tok->previous(), "delete (") && Token::Match(tok->link(), ") ;|,")) ||
|
if (!Token::simpleMatch(tok->tokAt(-2), "operator delete") &&
|
||||||
(Token::simpleMatch(tok->previous(), "; (") && Token::Match(tok->link(), ") ;")))
|
Token::Match(tok->previous(), "delete|; (") &&
|
||||||
|
Token::Match(tok->link(), ") ;|,"))
|
||||||
{
|
{
|
||||||
tok->link()->deleteThis();
|
tok->link()->deleteThis();
|
||||||
tok->deleteThis();
|
tok->deleteThis();
|
||||||
|
|
|
@ -129,6 +129,8 @@ private:
|
||||||
TEST_CASE(const24); // ticket #1708
|
TEST_CASE(const24); // ticket #1708
|
||||||
TEST_CASE(const25); // ticket #1724
|
TEST_CASE(const25); // ticket #1724
|
||||||
TEST_CASE(const26); // ticket #1847
|
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(constoperator1); // operator< can often be const
|
||||||
TEST_CASE(constoperator2); // operator<<
|
TEST_CASE(constoperator2); // operator<<
|
||||||
TEST_CASE(constincdec); // increment/decrement => non-const
|
TEST_CASE(constincdec); // increment/decrement => non-const
|
||||||
|
@ -3611,6 +3613,45 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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"
|
||||||
|
"public:\n"
|
||||||
|
" A(){m_d=1.0; m_iRealVal=2.0;}\n"
|
||||||
|
" double dGetValue();\n"
|
||||||
|
"private:\n"
|
||||||
|
" double m_d;\n"
|
||||||
|
" double m_iRealVal;\n"
|
||||||
|
"};\n"
|
||||||
|
"double A::dGetValue() {\n"
|
||||||
|
" double dRet = m_iRealVal;\n"
|
||||||
|
" if( m_d != 0 )\n"
|
||||||
|
" return dRet / m_d;\n"
|
||||||
|
" return dRet;\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (style) The function 'A::dGetValue' can be const\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// increment/decrement => not const
|
// increment/decrement => not const
|
||||||
void constincdec()
|
void constincdec()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1930,7 +1930,7 @@ private:
|
||||||
" y + 1 );\n"
|
" y + 1 );\n"
|
||||||
" s = y[0]*y[1];\n"
|
" s = y[0]*y[1];\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// alloc..
|
// alloc..
|
||||||
|
|
|
@ -172,6 +172,7 @@ private:
|
||||||
TEST_CASE(removeParantheses5); // Ticket #392
|
TEST_CASE(removeParantheses5); // Ticket #392
|
||||||
TEST_CASE(removeParantheses6);
|
TEST_CASE(removeParantheses6);
|
||||||
TEST_CASE(removeParantheses7);
|
TEST_CASE(removeParantheses7);
|
||||||
|
TEST_CASE(removeParantheses8); // Ticket #1865
|
||||||
|
|
||||||
TEST_CASE(tokenize_double);
|
TEST_CASE(tokenize_double);
|
||||||
TEST_CASE(tokenize_strings);
|
TEST_CASE(tokenize_strings);
|
||||||
|
@ -3014,6 +3015,20 @@ private:
|
||||||
ASSERT_EQUALS(" ; delete p ; ( p ) = 0 ;", ostr.str());
|
ASSERT_EQUALS(" ; delete p ; ( p ) = 0 ;", ostr.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeParantheses8()
|
||||||
|
{
|
||||||
|
const char code[] = "struct foo {\n"
|
||||||
|
" void operator delete(void *obj, size_t sz);\n"
|
||||||
|
"}\n";
|
||||||
|
const std::string actual(tokenizeAndStringify(code));
|
||||||
|
|
||||||
|
const char expected[] = "struct foo {\n"
|
||||||
|
"void operator delete ( void * obj , size_t sz ) ;\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
ASSERT_EQUALS(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
void tokenize_double()
|
void tokenize_double()
|
||||||
{
|
{
|
||||||
const char code[] = "void f()\n"
|
const char code[] = "void f()\n"
|
||||||
|
|
Loading…
Reference in New Issue