Merge branch 'master' of github.com:danmar/cppcheck

This commit is contained in:
Zachary Blair 2010-07-19 07:49:44 -07:00
commit df1c911d84
8 changed files with 153 additions and 198 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);
};

View File

@ -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();

View File

@ -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()
{

View File

@ -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..

View File

@ -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"