Symbol database: Enhancements and fixes. Ticket: #1895
This commit is contained in:
parent
6a3befa720
commit
12523bc745
|
@ -68,32 +68,7 @@ void CheckClass::createSymbolDatabase()
|
||||||
new_info->classDef = tok;
|
new_info->classDef = tok;
|
||||||
|
|
||||||
// goto initial '{'
|
// goto initial '{'
|
||||||
const Token *tok2 = tok->tokAt(2);
|
const Token *tok2 = initBaseInfo(tok, new_info->derivedFrom);
|
||||||
while (tok2 && tok2->str() != "{")
|
|
||||||
{
|
|
||||||
// check for base classes
|
|
||||||
if (Token::Match(tok2, ":|, public|protected|private"))
|
|
||||||
{
|
|
||||||
// jump to base class name
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
|
|
||||||
std::string derivedFrom;
|
|
||||||
|
|
||||||
// handle derived base classes
|
|
||||||
while (Token::Match(tok2, "%var% ::"))
|
|
||||||
{
|
|
||||||
derivedFrom += tok2->str();
|
|
||||||
derivedFrom += " :: ";
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
derivedFrom += tok2->str();
|
|
||||||
|
|
||||||
// save pattern for base class name
|
|
||||||
new_info->derivedFrom.push_back(derivedFrom);
|
|
||||||
}
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
new_info->classStart = tok2;
|
new_info->classStart = tok2;
|
||||||
new_info->classEnd = new_info->classStart->link();
|
new_info->classEnd = new_info->classStart->link();
|
||||||
|
@ -158,11 +133,15 @@ void CheckClass::createSymbolDatabase()
|
||||||
{
|
{
|
||||||
if (function.tokenDef->previous()->str() == "~")
|
if (function.tokenDef->previous()->str() == "~")
|
||||||
function.type = Func::Destructor;
|
function.type = Func::Destructor;
|
||||||
else if (Token::Match(function.tokenDef, "%var% ( const %var% & %var%| )") &&
|
else if ((Token::Match(function.tokenDef, "%var% ( const %var% & )") ||
|
||||||
|
Token::Match(function.tokenDef, "%var% ( const %var% & %var% )")) &&
|
||||||
function.tokenDef->strAt(3) == info->className)
|
function.tokenDef->strAt(3) == info->className)
|
||||||
function.type = Func::CopyConstructor;
|
function.type = Func::CopyConstructor;
|
||||||
else
|
else
|
||||||
function.type = Func::Constructor;
|
function.type = Func::Constructor;
|
||||||
|
|
||||||
|
if (function.tokenDef->previous()->str() == "explicit")
|
||||||
|
function.isExplicit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token *tok1 = tok;
|
const Token *tok1 = tok;
|
||||||
|
@ -198,6 +177,10 @@ void CheckClass::createSymbolDatabase()
|
||||||
if (function.tokenDef->next()->link()->next()->str() == "const")
|
if (function.tokenDef->next()->link()->next()->str() == "const")
|
||||||
function.isConst = true;
|
function.isConst = true;
|
||||||
|
|
||||||
|
// pure virtual function
|
||||||
|
if (Token::Match(function.tokenDef->next()->link(), ") const| = 0 ;"))
|
||||||
|
function.isPure = true;
|
||||||
|
|
||||||
// count the number of constructors
|
// count the number of constructors
|
||||||
if (function.type == Func::Constructor || function.type == Func::CopyConstructor)
|
if (function.type == Func::Constructor || function.type == Func::CopyConstructor)
|
||||||
info->numConstructors++;
|
info->numConstructors++;
|
||||||
|
@ -314,6 +297,61 @@ CheckClass::~CheckClass()
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const Token *CheckClass::initBaseInfo(const Token *tok, std::vector<BaseInfo> &derivedFrom)
|
||||||
|
{
|
||||||
|
// goto initial '{'
|
||||||
|
const Token *tok2 = tok->tokAt(2);
|
||||||
|
while (tok2 && tok2->str() != "{")
|
||||||
|
{
|
||||||
|
// check for base classes
|
||||||
|
if (Token::Match(tok2, ":|,"))
|
||||||
|
{
|
||||||
|
BaseInfo base;
|
||||||
|
|
||||||
|
tok2 = tok2->next();
|
||||||
|
|
||||||
|
if (tok2->str() == "public")
|
||||||
|
{
|
||||||
|
base.access = Public;
|
||||||
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
else if (tok2->str() == "protected")
|
||||||
|
{
|
||||||
|
base.access = Protected;
|
||||||
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
else if (tok2->str() == "private")
|
||||||
|
{
|
||||||
|
base.access = Private;
|
||||||
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tok->str() == "class")
|
||||||
|
base.access = Private;
|
||||||
|
else if (tok->str() == "struct")
|
||||||
|
base.access = Public;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle derived base classes
|
||||||
|
while (Token::Match(tok2, "%var% ::"))
|
||||||
|
{
|
||||||
|
base.name += tok2->str();
|
||||||
|
base.name += " :: ";
|
||||||
|
tok2 = tok2->tokAt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.name += tok2->str();
|
||||||
|
|
||||||
|
// save pattern for base class name
|
||||||
|
derivedFrom.push_back(base);
|
||||||
|
}
|
||||||
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tok2;
|
||||||
|
}
|
||||||
|
|
||||||
CheckClass::Var *CheckClass::getVarList(const Token *tok1)
|
CheckClass::Var *CheckClass::getVarList(const Token *tok1)
|
||||||
{
|
{
|
||||||
// Get variable list..
|
// Get variable list..
|
||||||
|
@ -842,6 +880,10 @@ void CheckClass::constructors()
|
||||||
{
|
{
|
||||||
SpaceInfo *info = i->second;
|
SpaceInfo *info = i->second;
|
||||||
|
|
||||||
|
// don't check namespaces
|
||||||
|
if (info->isNamespace)
|
||||||
|
continue;
|
||||||
|
|
||||||
// There are no constructors.
|
// There are no constructors.
|
||||||
if (info->numConstructors == 0)
|
if (info->numConstructors == 0)
|
||||||
{
|
{
|
||||||
|
@ -1276,33 +1318,6 @@ void CheckClass::operatorEqRetRefThis()
|
||||||
// assignment to self.
|
// assignment to self.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// match two lists of tokens
|
|
||||||
static bool nameMatch(const Token * tok1, const Token * tok2, int length)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
if (tok1->tokAt(i) == 0 || tok2->tokAt(i) == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (tok1->tokAt(i)->str() != tok2->tokAt(i)->str())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a class name from a list of tokens
|
|
||||||
static void nameStr(const Token * name, int length, std::string & str)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
if (i != 0)
|
|
||||||
str += " ";
|
|
||||||
|
|
||||||
str += name->tokAt(i)->str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hasDeallocation(const Token * first, const Token * last)
|
static bool hasDeallocation(const Token * first, const Token * last)
|
||||||
{
|
{
|
||||||
// This function is called when no simple check was found for assignment
|
// This function is called when no simple check was found for assignment
|
||||||
|
@ -1408,99 +1423,47 @@ static bool hasAssignSelf(const Token * first, const Token * last, const Token *
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasMultipleInheritanceInline(const Token * tok)
|
|
||||||
{
|
|
||||||
while (tok && tok->str() != "{")
|
|
||||||
{
|
|
||||||
if (tok->str() == ",")
|
|
||||||
return true;
|
|
||||||
|
|
||||||
tok = tok->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hasMultipleInheritanceGlobal(const Token * start, const std::string & name)
|
|
||||||
{
|
|
||||||
const Token *tok = start;
|
|
||||||
std::string pattern;
|
|
||||||
std::string className = name;
|
|
||||||
|
|
||||||
// check for nested classes
|
|
||||||
while (className.find("::") != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string tempName;
|
|
||||||
|
|
||||||
// there is probably a better way to do this
|
|
||||||
while (className[0] != ' ')
|
|
||||||
{
|
|
||||||
tempName += className[0];
|
|
||||||
className.erase(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
className.erase(0, 4);
|
|
||||||
|
|
||||||
pattern = "class|struct " + tempName;
|
|
||||||
|
|
||||||
tok = Token::findmatch(tok, pattern.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern = "class|struct " + className;
|
|
||||||
|
|
||||||
tok = Token::findmatch(tok, pattern.c_str());
|
|
||||||
|
|
||||||
return hasMultipleInheritanceInline(tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckClass::operatorEqToSelf()
|
void CheckClass::operatorEqToSelf()
|
||||||
{
|
{
|
||||||
if (!_settings->_checkCodingStyle)
|
if (!_settings->_checkCodingStyle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Token *tok2 = _tokenizer->tokens();
|
createSymbolDatabase();
|
||||||
const Token *tok;
|
|
||||||
|
|
||||||
while ((tok = Token::findmatch(tok2, "operator = (")) != NULL)
|
std::multimap<std::string, SpaceInfo *>::const_iterator i;
|
||||||
|
|
||||||
|
for (i = spaceInfoMMap.begin(); i != spaceInfoMMap.end(); ++i)
|
||||||
{
|
{
|
||||||
|
const SpaceInfo *info = i->second;
|
||||||
|
std::list<Func>::const_iterator it;
|
||||||
|
|
||||||
|
// skip classes with multiple inheritance
|
||||||
|
if (info->derivedFrom.size() > 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (it = info->functionList.begin(); it != info->functionList.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->type == Func::OperatorEqual && it->hasBody)
|
||||||
|
{
|
||||||
|
// make sure return signature is correct
|
||||||
|
if (Token::Match(it->tokenDef->tokAt(-4), ";|}|{|public:|protected:|private: %type% &") &&
|
||||||
|
it->tokenDef->strAt(-3) == info->className)
|
||||||
|
{
|
||||||
|
// check for proper function parameter signature
|
||||||
|
if ((Token::Match(it->tokenDef->next(), "( const %var% & )") ||
|
||||||
|
Token::Match(it->tokenDef->next(), "( const %var% & %var% )")) &&
|
||||||
|
it->tokenDef->strAt(3) == info->className)
|
||||||
|
{
|
||||||
|
// find the parameter name
|
||||||
|
const Token *rhs = it->token;
|
||||||
|
while (rhs->str() != "&")
|
||||||
|
rhs = rhs->next();
|
||||||
|
rhs = rhs->next();
|
||||||
|
|
||||||
|
// find the ')'
|
||||||
|
const Token *tok = it->token->next()->link();
|
||||||
const Token *tok1 = tok;
|
const Token *tok1 = tok;
|
||||||
|
|
||||||
// make sure this is an assignment operator
|
|
||||||
if (tok1->tokAt(-2) && Token::Match(tok1->tokAt(-2), " %type% ::"))
|
|
||||||
{
|
|
||||||
int nameLength = 1;
|
|
||||||
|
|
||||||
tok1 = tok1->tokAt(-2);
|
|
||||||
|
|
||||||
// check backwards for proper function signature
|
|
||||||
while (tok1->tokAt(-2) && Token::Match(tok1->tokAt(-2), " %type% ::"))
|
|
||||||
{
|
|
||||||
tok1 = tok1->tokAt(-2);
|
|
||||||
nameLength += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token *className = tok1;
|
|
||||||
std::string nameString;
|
|
||||||
|
|
||||||
nameStr(className, nameLength, nameString);
|
|
||||||
|
|
||||||
if (!hasMultipleInheritanceGlobal(_tokenizer->tokens(), nameString))
|
|
||||||
{
|
|
||||||
if (tok1->tokAt(-1) && tok1->tokAt(-1)->str() == "&")
|
|
||||||
{
|
|
||||||
// check returned class name
|
|
||||||
if (tok1->tokAt(-(1 + nameLength)) && nameMatch(className, tok1->tokAt(-(1 + nameLength)), nameLength))
|
|
||||||
{
|
|
||||||
// check forward for proper function signature
|
|
||||||
std::string pattern = "const " + nameString + " & %var% )";
|
|
||||||
if (Token::Match(tok->tokAt(3), pattern.c_str()))
|
|
||||||
{
|
|
||||||
const Token * rhs = tok->tokAt(5 + nameLength);
|
|
||||||
|
|
||||||
if (nameMatch(className, tok->tokAt(4), nameLength))
|
|
||||||
{
|
|
||||||
tok1 = tok->tokAt(2)->link();
|
|
||||||
|
|
||||||
if (tok1 && tok1->tokAt(1) && tok1->tokAt(1)->str() == "{" && tok1->tokAt(1)->link())
|
if (tok1 && tok1->tokAt(1) && tok1->tokAt(1)->str() == "{" && tok1->tokAt(1)->link())
|
||||||
{
|
{
|
||||||
const Token *first = tok1->tokAt(1);
|
const Token *first = tok1->tokAt(1);
|
||||||
|
@ -1517,54 +1480,6 @@ void CheckClass::operatorEqToSelf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tok1 = tok;
|
|
||||||
|
|
||||||
// check backwards for proper function signature
|
|
||||||
if (tok1->tokAt(-1) && tok1->tokAt(-1)->str() == "&")
|
|
||||||
{
|
|
||||||
const Token *className = 0;
|
|
||||||
while (tok1 && !Token::Match(tok1, "class|struct %var%"))
|
|
||||||
tok1 = tok1->previous();
|
|
||||||
|
|
||||||
if (Token::Match(tok1, "struct|class %var%"))
|
|
||||||
className = tok1->tokAt(1);
|
|
||||||
|
|
||||||
if (!hasMultipleInheritanceInline(tok1))
|
|
||||||
{
|
|
||||||
if (Token::simpleMatch(tok->tokAt(-2), className->str().c_str()))
|
|
||||||
{
|
|
||||||
// check forward for proper function signature
|
|
||||||
if (Token::Match(tok->tokAt(3), "const %type% & %var% )"))
|
|
||||||
{
|
|
||||||
const Token * rhs = tok->tokAt(6);
|
|
||||||
|
|
||||||
if (tok->tokAt(4)->str() == className->str())
|
|
||||||
{
|
|
||||||
tok1 = tok->tokAt(2)->link();
|
|
||||||
|
|
||||||
if (tok1 && Token::simpleMatch(tok1->next(), "{"))
|
|
||||||
{
|
|
||||||
const Token *first = tok1->next();
|
|
||||||
const Token *last = first->link();
|
|
||||||
|
|
||||||
if (!hasAssignSelf(first, last, rhs))
|
|
||||||
{
|
|
||||||
if (hasDeallocation(first, last))
|
|
||||||
operatorEqToSelfError(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tok2 = tok->next();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1744,19 +1659,19 @@ void CheckClass::thisSubtraction()
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// check if this function is defined virtual in the base classes
|
// check if this function is defined virtual in the base classes
|
||||||
bool CheckClass::isVirtual(const std::vector<std::string> &derivedFrom, const Token *functionToken) const
|
bool CheckClass::isVirtual(const std::vector<BaseInfo> &derivedFrom, const Token *functionToken) const
|
||||||
{
|
{
|
||||||
// check each base class
|
// check each base class
|
||||||
for (unsigned int i = 0; i < derivedFrom.size(); ++i)
|
for (unsigned int i = 0; i < derivedFrom.size(); ++i)
|
||||||
{
|
{
|
||||||
std::string className;
|
std::string className;
|
||||||
|
|
||||||
if (derivedFrom[i].find("::") != std::string::npos)
|
if (derivedFrom[i].name.find("::") != std::string::npos)
|
||||||
{
|
{
|
||||||
/** @todo handle nested base classes and namespaces */
|
/** @todo handle nested base classes and namespaces */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
className = derivedFrom[i];
|
className = derivedFrom[i].name;
|
||||||
|
|
||||||
std::string classPattern = std::string("class|struct ") + className + std::string(" {|:");
|
std::string classPattern = std::string("class|struct ") + className + std::string(" {|:");
|
||||||
|
|
||||||
|
@ -1766,34 +1681,8 @@ bool CheckClass::isVirtual(const std::vector<std::string> &derivedFrom, const To
|
||||||
// find the function in the base class
|
// find the function in the base class
|
||||||
if (classToken)
|
if (classToken)
|
||||||
{
|
{
|
||||||
std::vector<std::string> baseList;
|
std::vector<BaseInfo> baseList;
|
||||||
const Token * tok = classToken;
|
const Token *tok = initBaseInfo(classToken, baseList);
|
||||||
|
|
||||||
while (tok->str() != "{")
|
|
||||||
{
|
|
||||||
// check for base classes
|
|
||||||
if (Token::Match(tok, ":|, public|protected|private"))
|
|
||||||
{
|
|
||||||
// jump to base class name
|
|
||||||
tok = tok->tokAt(2);
|
|
||||||
|
|
||||||
std::string base;
|
|
||||||
|
|
||||||
// handle nested base classea and namespacess
|
|
||||||
while (Token::Match(tok, "%var% ::"))
|
|
||||||
{
|
|
||||||
base += tok->str();
|
|
||||||
base += " :: ";
|
|
||||||
tok = tok->tokAt(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
base += tok->str();
|
|
||||||
|
|
||||||
// save pattern for base class name
|
|
||||||
baseList.push_back(base);
|
|
||||||
}
|
|
||||||
tok = tok->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
|
@ -1962,7 +1851,7 @@ void CheckClass::checkConst()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckClass::isMemberVar(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok)
|
bool CheckClass::isMemberVar(const std::string &classname, const std::vector<BaseInfo> &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|:|?"))
|
||||||
{
|
{
|
||||||
|
@ -1998,12 +1887,12 @@ bool CheckClass::isMemberVar(const std::string &classname, const std::vector<std
|
||||||
{
|
{
|
||||||
std::string className;
|
std::string className;
|
||||||
|
|
||||||
if (derivedFrom[i].find("::") != std::string::npos)
|
if (derivedFrom[i].name.find("::") != std::string::npos)
|
||||||
{
|
{
|
||||||
/** @todo handle nested base classes and namespaces */
|
/** @todo handle nested base classes and namespaces */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
className = derivedFrom[i];
|
className = derivedFrom[i].name;
|
||||||
|
|
||||||
std::string classPattern = std::string("class|struct ") + className + std::string(" {|:");
|
std::string classPattern = std::string("class|struct ") + className + std::string(" {|:");
|
||||||
|
|
||||||
|
@ -2013,34 +1902,9 @@ bool CheckClass::isMemberVar(const std::string &classname, const std::vector<std
|
||||||
// find the function in the base class
|
// find the function in the base class
|
||||||
if (classToken)
|
if (classToken)
|
||||||
{
|
{
|
||||||
std::vector<std::string> baseList;
|
std::vector<BaseInfo> baseList;
|
||||||
const Token * tok1 = classToken;
|
|
||||||
|
|
||||||
while (tok1->str() != "{")
|
initBaseInfo(classToken, baseList);
|
||||||
{
|
|
||||||
// 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...
|
// Get class variables...
|
||||||
Var *varlist1 = getVarList(classToken);
|
Var *varlist1 = getVarList(classToken);
|
||||||
|
@ -2054,7 +1918,7 @@ bool CheckClass::isMemberVar(const std::string &classname, const std::vector<std
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckClass::checkConstFunc(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok)
|
bool CheckClass::checkConstFunc(const std::string &classname, const std::vector<BaseInfo> &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..
|
||||||
|
|
|
@ -180,8 +180,10 @@ private:
|
||||||
isInline(false),
|
isInline(false),
|
||||||
isConst(false),
|
isConst(false),
|
||||||
isVirtual(false),
|
isVirtual(false),
|
||||||
|
isPure(false),
|
||||||
isStatic(false),
|
isStatic(false),
|
||||||
isFriend(false),
|
isFriend(false),
|
||||||
|
isExplicit(false),
|
||||||
isOperator(false),
|
isOperator(false),
|
||||||
type(Function)
|
type(Function)
|
||||||
{
|
{
|
||||||
|
@ -194,12 +196,20 @@ private:
|
||||||
bool isInline; // implementation in class definition
|
bool isInline; // implementation in class definition
|
||||||
bool isConst; // is const
|
bool isConst; // is const
|
||||||
bool isVirtual; // is virtual
|
bool isVirtual; // is virtual
|
||||||
|
bool isPure; // is pure virtual
|
||||||
bool isStatic; // is static
|
bool isStatic; // is static
|
||||||
bool isFriend; // is friend
|
bool isFriend; // is friend
|
||||||
|
bool isExplicit; // is explicit
|
||||||
bool isOperator; // is operator
|
bool isOperator; // is operator
|
||||||
Type type; // constructor, destructor, ...
|
Type type; // constructor, destructor, ...
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BaseInfo
|
||||||
|
{
|
||||||
|
AccessControl access; // public/protected/private
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
struct SpaceInfo
|
struct SpaceInfo
|
||||||
{
|
{
|
||||||
bool isNamespace;
|
bool isNamespace;
|
||||||
|
@ -210,7 +220,7 @@ private:
|
||||||
unsigned int numConstructors;
|
unsigned int numConstructors;
|
||||||
std::list<Func> functionList;
|
std::list<Func> functionList;
|
||||||
Var *varlist;
|
Var *varlist;
|
||||||
std::vector<std::string> derivedFrom;
|
std::vector<BaseInfo> derivedFrom;
|
||||||
SpaceInfo *nest;
|
SpaceInfo *nest;
|
||||||
AccessControl access;
|
AccessControl access;
|
||||||
};
|
};
|
||||||
|
@ -238,11 +248,13 @@ private:
|
||||||
*/
|
*/
|
||||||
Var *getVarList(const Token *tok1);
|
Var *getVarList(const Token *tok1);
|
||||||
|
|
||||||
bool isMemberVar(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
bool isMemberVar(const std::string &classname, const std::vector<BaseInfo> &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);
|
bool checkConstFunc(const std::string &classname, const std::vector<BaseInfo> &derivedFrom, const Var *varlist, const Token *tok);
|
||||||
|
|
||||||
|
static const Token *initBaseInfo(const Token *tok, std::vector<BaseInfo> &derivedFrom);
|
||||||
|
|
||||||
/** @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<BaseInfo> &derivedFrom, const Token *functionToken) const;
|
||||||
|
|
||||||
// Reporting errors..
|
// Reporting errors..
|
||||||
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct);
|
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct);
|
||||||
|
|
|
@ -84,6 +84,7 @@ private:
|
||||||
TEST_CASE(noConstructor2);
|
TEST_CASE(noConstructor2);
|
||||||
TEST_CASE(noConstructor3);
|
TEST_CASE(noConstructor3);
|
||||||
TEST_CASE(noConstructor4);
|
TEST_CASE(noConstructor4);
|
||||||
|
TEST_CASE(noConstructor5);
|
||||||
|
|
||||||
TEST_CASE(operatorEq1);
|
TEST_CASE(operatorEq1);
|
||||||
TEST_CASE(operatorEqRetRefThis1);
|
TEST_CASE(operatorEqRetRefThis1);
|
||||||
|
@ -516,7 +517,7 @@ private:
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" A & operator=(const A &)\n"
|
" A & operator=(const A &);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"A & A::operator=(const A &a) { return *this; }\n");
|
"A & A::operator=(const A &a) { return *this; }\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
@ -529,7 +530,7 @@ private:
|
||||||
" char *s;\n"
|
" char *s;\n"
|
||||||
" A & operator=(const A &);\n"
|
" A & operator=(const A &);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"A & operator=(const A &a)\n"
|
"A & A::operator=(const A &a)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (&a != this)\n"
|
" if (&a != this)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
|
@ -548,7 +549,7 @@ private:
|
||||||
" char *s;\n"
|
" char *s;\n"
|
||||||
" A & operator=(const A &);\n"
|
" A & operator=(const A &);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"A & operator=(const A &a)\n"
|
"A & A::operator=(const A &a)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" free(s);\n"
|
" free(s);\n"
|
||||||
" s = strdup(a.s);\n"
|
" s = strdup(a.s);\n"
|
||||||
|
@ -2210,6 +2211,15 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void noConstructor5()
|
||||||
|
{
|
||||||
|
checkNoConstructor("namespace Foo\n"
|
||||||
|
"{\n"
|
||||||
|
" int i;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void checkNoMemset(const char code[])
|
void checkNoMemset(const char code[])
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
|
|
Loading…
Reference in New Issue