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 (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;
|
||||
|
@ -2329,7 +2390,7 @@ bool CheckClass::checkConstFunc(const std::string &classname, const Var *varlist
|
|||
}
|
||||
|
||||
// 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% > ("))
|
||||
{
|
||||
isconst = false;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -3395,6 +3395,22 @@ private:
|
|||
// it is possible that the variable is initialized here
|
||||
if (Token::Match(tok2->previous(), "[(,] %var% [,)]"))
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// THIS FILE IS GENERATED BY MACHINE, SEE ../tools/errmsg.cpp !
|
||||
|
||||
#ifndef errorloggerH
|
||||
#define errorloggerH
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "settings.h"
|
||||
|
@ -153,189 +153,6 @@ public:
|
|||
*/
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
@ -5735,8 +5735,9 @@ bool Tokenizer::simplifyRedundantParanthesis()
|
|||
ret = true;
|
||||
}
|
||||
|
||||
if ((Token::simpleMatch(tok->previous(), "delete (") && Token::Match(tok->link(), ") ;|,")) ||
|
||||
(Token::simpleMatch(tok->previous(), "; (") && Token::Match(tok->link(), ") ;")))
|
||||
if (!Token::simpleMatch(tok->tokAt(-2), "operator delete") &&
|
||||
Token::Match(tok->previous(), "delete|; (") &&
|
||||
Token::Match(tok->link(), ") ;|,"))
|
||||
{
|
||||
tok->link()->deleteThis();
|
||||
tok->deleteThis();
|
||||
|
|
|
@ -129,6 +129,8 @@ private:
|
|||
TEST_CASE(const24); // ticket #1708
|
||||
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
|
||||
|
@ -3611,6 +3613,45 @@ 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"
|
||||
"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
|
||||
void constincdec()
|
||||
{
|
||||
|
|
|
@ -1930,7 +1930,7 @@ private:
|
|||
" y + 1 );\n"
|
||||
" s = y[0]*y[1];\n"
|
||||
"}\n");
|
||||
TODO_ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
// alloc..
|
||||
|
|
|
@ -165,13 +165,14 @@ private:
|
|||
|
||||
TEST_CASE(simplify_function_parameters);
|
||||
|
||||
TEST_CASE(removeParantheses1); // Ticket #61
|
||||
TEST_CASE(removeParantheses1); // Ticket #61
|
||||
TEST_CASE(removeParantheses2);
|
||||
TEST_CASE(removeParantheses3);
|
||||
TEST_CASE(removeParantheses4); // Ticket #390
|
||||
TEST_CASE(removeParantheses5); // Ticket #392
|
||||
TEST_CASE(removeParantheses6);
|
||||
TEST_CASE(removeParantheses7);
|
||||
TEST_CASE(removeParantheses8); // Ticket #1865
|
||||
|
||||
TEST_CASE(tokenize_double);
|
||||
TEST_CASE(tokenize_strings);
|
||||
|
@ -3014,6 +3015,20 @@ private:
|
|||
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()
|
||||
{
|
||||
const char code[] = "void f()\n"
|
||||
|
|
Loading…
Reference in New Issue