Fixed #6422 (symbol database: put function flags into a single flag variable)
This commit is contained in:
parent
2b018db25a
commit
ba1c24ee65
|
@ -53,7 +53,7 @@ void Check64BitPortability::pointerassignment()
|
|||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
|
||||
if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body
|
||||
continue;
|
||||
|
||||
bool retPointer = false;
|
||||
|
|
|
@ -47,7 +47,7 @@ void CheckAssert::assertWithSideEffects()
|
|||
if (tmp->type() == Token::eFunction) {
|
||||
const Function* f = tmp->function();
|
||||
|
||||
if (f->nestedIn->isClassOrStruct() && !f->isStatic && !f->isConst)
|
||||
if (f->nestedIn->isClassOrStruct() && !f->isStatic() && !f->isConst())
|
||||
sideEffectInAssertError(tmp, f->name()); // Non-const member function called
|
||||
else {
|
||||
const Scope* scope = f->functionScope;
|
||||
|
|
|
@ -367,7 +367,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &ftok, unsigned int
|
|||
else if (arrayInfo.num().size() == 1) {
|
||||
const Function* const func = ftok.function();
|
||||
|
||||
if (func && func->hasBody) {
|
||||
if (func && func->hasBody()) {
|
||||
// Get corresponding parameter..
|
||||
const Variable* const parameter = func->getArgumentVar(par-1);
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace {
|
|||
|
||||
inline bool isPureWithoutBody(Function const & func)
|
||||
{
|
||||
return func.isPure && !func.hasBody;
|
||||
return func.isPure() && !func.hasBody();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,8 +120,8 @@ void CheckClass::constructors()
|
|||
std::vector<Usage> usage(scope->varlist.size());
|
||||
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
if (!func->hasBody || !(func->isConstructor() ||
|
||||
func->type == Function::eOperatorEqual))
|
||||
if (!func->hasBody() || !(func->isConstructor() ||
|
||||
func->type == Function::eOperatorEqual))
|
||||
continue;
|
||||
|
||||
// Mark all variables not used
|
||||
|
@ -143,7 +143,7 @@ void CheckClass::constructors()
|
|||
if (usage[count].assign || usage[count].init || var->isStatic())
|
||||
continue;
|
||||
|
||||
if (var->isConst() && func->isOperator) // We can't set const members in assignment operator
|
||||
if (var->isConst() && func->isOperator()) // We can't set const members in assignment operator
|
||||
continue;
|
||||
|
||||
// Check if this is a class constructor
|
||||
|
@ -456,7 +456,7 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
|
|||
}
|
||||
|
||||
// member function has implementation
|
||||
if (member->hasBody) {
|
||||
if (member->hasBody()) {
|
||||
// initialize variable use list using member function
|
||||
callstack.push_back(member);
|
||||
initializeVarList(*member, callstack, scope, usage);
|
||||
|
@ -584,7 +584,7 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
|
|||
}
|
||||
|
||||
// member function has implementation
|
||||
if (member->hasBody) {
|
||||
if (member->hasBody()) {
|
||||
// initialize variable use list using member function
|
||||
callstack.push_back(member);
|
||||
initializeVarList(*member, callstack, scope, usage);
|
||||
|
@ -626,7 +626,7 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
|
|||
}
|
||||
|
||||
// member function has implementation
|
||||
if (member->hasBody) {
|
||||
if (member->hasBody()) {
|
||||
// initialize variable use list using member function
|
||||
callstack.push_back(member);
|
||||
initializeVarList(*member, callstack, scope, usage);
|
||||
|
@ -864,7 +864,7 @@ void CheckClass::privateFunctions()
|
|||
std::list<const Function*> privateFuncs;
|
||||
for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
// Get private functions..
|
||||
if (func->type == Function::eFunction && func->access == Private && !func->isOperator) // TODO: There are smarter ways to check private operator usage
|
||||
if (func->type == Function::eFunction && func->access == Private && !func->isOperator()) // TODO: There are smarter ways to check private operator usage
|
||||
privateFuncs.push_back(&*func);
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco
|
|||
std::list<Function>::const_iterator func;
|
||||
|
||||
for (func = type->functionList.begin(); func != type->functionList.end(); ++func) {
|
||||
if (func->isVirtual) {
|
||||
if (func->isVirtual()) {
|
||||
if (allocation)
|
||||
mallocOnClassError(tok, tok->str(), type->classDef, "virtual method");
|
||||
else
|
||||
|
@ -1119,7 +1119,7 @@ void CheckClass::operatorEq()
|
|||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
if (func->type == Function::eOperatorEqual && func->access == Public) {
|
||||
// skip "deleted" functions - cannot be called anyway
|
||||
if (func->isDelete)
|
||||
if (func->isDelete())
|
||||
continue;
|
||||
// use definition for check so we don't have to deal with qualification
|
||||
if (!(Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className)) {
|
||||
|
@ -1160,7 +1160,7 @@ void CheckClass::operatorEqRetRefThis()
|
|||
std::list<Function>::const_iterator func;
|
||||
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
if (func->type == Function::eOperatorEqual && func->hasBody) {
|
||||
if (func->type == Function::eOperatorEqual && func->hasBody()) {
|
||||
// make sure return signature is correct
|
||||
if (Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className) {
|
||||
checkReturnPtrThis(&(*scope), &(*func), func->functionScope->classStart, func->functionScope->classEnd);
|
||||
|
@ -1196,13 +1196,13 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co
|
|||
// check if it is a member function
|
||||
for (it = scope->functionList.begin(); it != scope->functionList.end(); ++it) {
|
||||
// check for a regular function with the same name and a body
|
||||
if (it->type == Function::eFunction && it->hasBody &&
|
||||
if (it->type == Function::eFunction && it->hasBody() &&
|
||||
it->token->str() == tok->next()->str()) {
|
||||
// check for the proper return type
|
||||
if (it->tokenDef->previous()->str() == "&" &&
|
||||
it->tokenDef->strAt(-2) == scope->className) {
|
||||
// make sure it's not a const function
|
||||
if (!it->isConst) {
|
||||
if (!it->isConst()) {
|
||||
/** @todo make sure argument types match */
|
||||
// avoid endless recursions
|
||||
if (analyzedFunctions.find(&*it) == analyzedFunctions.end()) {
|
||||
|
@ -1265,7 +1265,7 @@ void CheckClass::operatorEqToSelf()
|
|||
|
||||
std::list<Function>::const_iterator func;
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
if (func->type == Function::eOperatorEqual && func->hasBody) {
|
||||
if (func->type == Function::eOperatorEqual && func->hasBody()) {
|
||||
// make sure that the operator takes an object of the same type as *this, otherwise we can't detect self-assignment checks
|
||||
if (func->argumentList.empty())
|
||||
continue;
|
||||
|
@ -1381,10 +1381,10 @@ void CheckClass::virtualDestructor()
|
|||
if (scope->definedType->derivedFrom.empty()) {
|
||||
if (_settings->inconclusive) {
|
||||
const Function *destructor = scope->getDestructor();
|
||||
if (destructor && !destructor->isVirtual) {
|
||||
if (destructor && !destructor->isVirtual()) {
|
||||
std::list<Function>::const_iterator func;
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
if (func->isVirtual) {
|
||||
if (func->isVirtual()) {
|
||||
inconclusive_errors.push_back(destructor);
|
||||
break;
|
||||
}
|
||||
|
@ -1398,7 +1398,7 @@ void CheckClass::virtualDestructor()
|
|||
const Function *destructor = scope->getDestructor();
|
||||
|
||||
// Check for destructor with implementation
|
||||
if (!destructor || !destructor->hasBody)
|
||||
if (!destructor || !destructor->hasBody())
|
||||
continue;
|
||||
|
||||
// Empty destructor
|
||||
|
@ -1477,7 +1477,7 @@ void CheckClass::virtualDestructor()
|
|||
if (found != inconclusive_errors.end())
|
||||
inconclusive_errors.erase(found);
|
||||
}
|
||||
} else if (!base_destructor->isVirtual) {
|
||||
} else if (!base_destructor->isVirtual()) {
|
||||
// TODO: This is just a temporary fix, better solution is needed.
|
||||
// Skip situations where base class has base classes of its own, because
|
||||
// some of the base classes might have virtual destructor.
|
||||
|
@ -1564,7 +1564,7 @@ void CheckClass::checkConst()
|
|||
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
// does the function have a body?
|
||||
if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isVirtual) {
|
||||
if (func->type == Function::eFunction && func->hasBody() && !func->isFriend() && !func->isStatic() && !func->isVirtual()) {
|
||||
// get last token of return type
|
||||
const Token *previous = func->tokenDef->previous();
|
||||
|
||||
|
@ -1586,7 +1586,7 @@ void CheckClass::checkConst()
|
|||
|
||||
if (!foundConst)
|
||||
continue;
|
||||
} else if (func->isOperator && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator
|
||||
} else if (func->isOperator() && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator
|
||||
const std::string& opName = func->tokenDef->str();
|
||||
if (opName.compare(8, 5, "const") != 0 && opName[opName.size()-1] == '&')
|
||||
continue;
|
||||
|
@ -1621,11 +1621,11 @@ void CheckClass::checkConst()
|
|||
else if (func->tokenDef->str() == "[")
|
||||
functionName += "]";
|
||||
|
||||
if (!func->isConst || (!memberAccessed && !func->isOperator)) {
|
||||
if (func->isInline)
|
||||
checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator);
|
||||
if (!func->isConst() || (!memberAccessed && !func->isOperator())) {
|
||||
if (func->isInline())
|
||||
checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator());
|
||||
else // not inline
|
||||
checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator);
|
||||
checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1688,7 +1688,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const
|
|||
bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
|
||||
{
|
||||
if (tok->function() && tok->function()->nestedIn == scope)
|
||||
return !tok->function()->isStatic;
|
||||
return !tok->function()->isStatic();
|
||||
|
||||
// not found in this class
|
||||
if (!scope->definedType->derivedFrom.empty()) {
|
||||
|
@ -1711,7 +1711,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
|
|||
bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const
|
||||
{
|
||||
if (tok->function() && tok->function()->nestedIn == scope)
|
||||
return tok->function()->isConst;
|
||||
return tok->function()->isConst();
|
||||
|
||||
// not found in this class
|
||||
if (!scope->definedType->derivedFrom.empty()) {
|
||||
|
@ -1919,7 +1919,7 @@ void CheckClass::initializerListOrder()
|
|||
|
||||
// iterate through all member functions looking for constructors
|
||||
for (func = info->functionList.begin(); func != info->functionList.end(); ++func) {
|
||||
if ((func->isConstructor()) && func->hasBody) {
|
||||
if ((func->isConstructor()) && func->hasBody()) {
|
||||
// check for initializer list
|
||||
const Token *tok = func->arg->link()->next();
|
||||
|
||||
|
@ -2015,7 +2015,7 @@ void CheckClass::checkPureVirtualFunctionCall()
|
|||
std::map<const Function *, std::list<const Token *> > callsPureVirtualFunctionMap;
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
if (scope->function == 0 || !scope->function->hasBody ||
|
||||
if (scope->function == 0 || !scope->function->hasBody() ||
|
||||
!(scope->function->isConstructor() ||
|
||||
scope->function->isDestructor()))
|
||||
continue;
|
||||
|
@ -2041,7 +2041,7 @@ const std::list<const Token *> & CheckClass::callsPureVirtualFunction(const Func
|
|||
callsPureVirtualFunctionMap.insert(std::pair<const Function *, std::list< const Token *> >(&function, std::list<const Token *>()));
|
||||
std::list<const Token *> & pureFunctionCalls = found.first->second;
|
||||
if (found.second) {
|
||||
if (function.hasBody) {
|
||||
if (function.hasBody()) {
|
||||
for (const Token *tok = function.arg->link();
|
||||
tok && tok != function.functionScope->classEnd;
|
||||
tok = tok->next()) {
|
||||
|
|
|
@ -429,7 +429,7 @@ void CheckCondition::oppositeInnerCondition()
|
|||
if (tok->variable() &&
|
||||
Token::Match(tok, "%var% . %var% (") &&
|
||||
!tok->variable()->isConst() &&
|
||||
!(tok->tokAt(2)->function() && tok->tokAt(2)->function()->isConst))
|
||||
!(tok->tokAt(2)->function() && tok->tokAt(2)->function()->isConst()))
|
||||
break;
|
||||
if (Token::Match(tok->previous(), "[(,] %var% [,)]")) {
|
||||
// is variable unchanged? default is false..
|
||||
|
|
|
@ -206,9 +206,9 @@ static const Token * functionThrowsRecursive(const Function * function, std::set
|
|||
} else if (tok->function()) {
|
||||
const Function * called = tok->function();
|
||||
// check if called function has an exception specification
|
||||
if (called->isThrow && called->throwArg) {
|
||||
if (called->isThrow() && called->throwArg) {
|
||||
return tok;
|
||||
} else if (called->isNoExcept && called->noexceptArg &&
|
||||
} else if (called->isNoExcept() && called->noexceptArg &&
|
||||
called->noexceptArg->str() != "true") {
|
||||
return tok;
|
||||
} else if (functionThrowsRecursive(called, recursive)) {
|
||||
|
@ -244,7 +244,7 @@ void CheckExceptionSafety::nothrowThrows()
|
|||
continue;
|
||||
|
||||
// check noexcept functions
|
||||
if (function->isNoExcept &&
|
||||
if (function->isNoExcept() &&
|
||||
(!function->noexceptArg || function->noexceptArg->str() == "true")) {
|
||||
const Token *throws = functionThrows(function);
|
||||
if (throws)
|
||||
|
@ -252,7 +252,7 @@ void CheckExceptionSafety::nothrowThrows()
|
|||
}
|
||||
|
||||
// check throw() functions
|
||||
else if (function->isThrow && !function->throwArg) {
|
||||
else if (function->isThrow() && !function->throwArg) {
|
||||
const Token *throws = functionThrows(function);
|
||||
if (throws)
|
||||
nothrowThrowError(throws);
|
||||
|
@ -288,7 +288,7 @@ void CheckExceptionSafety::unhandledExceptionSpecification()
|
|||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
// only check functions without exception epecification
|
||||
if (scope->function && !scope->function->isThrow &&
|
||||
if (scope->function && !scope->function->isThrow() &&
|
||||
scope->className != "main" && scope->className != "wmain" &&
|
||||
scope->className != "_tmain" && scope->className != "WinMain") {
|
||||
for (const Token *tok = scope->function->functionScope->classStart->next();
|
||||
|
@ -298,7 +298,7 @@ void CheckExceptionSafety::unhandledExceptionSpecification()
|
|||
} else if (tok->function()) {
|
||||
const Function * called = tok->function();
|
||||
// check if called function has an exception specification
|
||||
if (called->isThrow && called->throwArg) {
|
||||
if (called->isThrow() && called->throwArg) {
|
||||
unhandledExceptionSpecificationError(tok, called->tokenDef, scope->function->name());
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ void CheckMemoryLeak::mismatchAllocDealloc(const std::list<const Token *> &calls
|
|||
|
||||
CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* func, std::list<const Function*> *callstack) const
|
||||
{
|
||||
if (!func || !func->hasBody)
|
||||
if (!func || !func->hasBody())
|
||||
return No;
|
||||
|
||||
// Get return pointer..
|
||||
|
@ -597,7 +597,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
|
|||
// lock/unlock..
|
||||
if (varid == 0) {
|
||||
const Function* func = tok->function();
|
||||
if (!func || !func->hasBody)
|
||||
if (!func || !func->hasBody())
|
||||
return 0;
|
||||
|
||||
Token *ftok = getcode(func->functionScope->classStart->next(), callstack, 0, alloctype, dealloctype, false, 1);
|
||||
|
@ -2317,7 +2317,7 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam
|
|||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
const bool constructor = func->isConstructor();
|
||||
const bool destructor = func->isDestructor();
|
||||
if (!func->hasBody) {
|
||||
if (!func->hasBody()) {
|
||||
if (destructor) { // implementation for destructor is not seen => assume it deallocates all variables properly
|
||||
deallocInDestructor = true;
|
||||
Dealloc = CheckMemoryLeak::Many;
|
||||
|
@ -2445,7 +2445,7 @@ void CheckMemoryLeakInClass::checkPublicFunctions(const Scope *scope, const Toke
|
|||
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
if ((func->type == Function::eFunction || func->type == Function::eOperatorEqual) &&
|
||||
func->access == Public && func->hasBody) {
|
||||
func->access == Public && func->hasBody()) {
|
||||
const Token *tok2 = func->token;
|
||||
while (tok2->str() != "{")
|
||||
tok2 = tok2->next();
|
||||
|
|
|
@ -379,7 +379,7 @@ void CheckNullPointer::nullConstantDereference()
|
|||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
|
||||
if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body
|
||||
continue;
|
||||
|
||||
const Token *tok = scope->classStart;
|
||||
|
@ -484,7 +484,7 @@ void CheckNullPointer::nullPointerDefaultArgument()
|
|||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body
|
||||
if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body
|
||||
continue;
|
||||
|
||||
// Scan the argument list for default arguments that are pointers and
|
||||
|
|
|
@ -66,7 +66,7 @@ static bool isConstExpression(const Token *tok, const std::set<std::string> &con
|
|||
if (tok->isName() && tok->next()->str() == "(") {
|
||||
if (!tok->function() && !Token::Match(tok->previous(), ".|::") && constFunctions.find(tok->str()) == constFunctions.end())
|
||||
return false;
|
||||
else if (tok->function() && !tok->function()->isConst)
|
||||
else if (tok->function() && !tok->function()->isConst())
|
||||
return false;
|
||||
}
|
||||
if (tok->type() == Token::eIncDecOp)
|
||||
|
@ -96,7 +96,7 @@ bool isSameExpression(const Token *tok1, const Token *tok2, const std::set<std::
|
|||
if (tok1->isName() && tok1->next()->str() == "(") {
|
||||
if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end() && !tok1->isAttributeConst() && !tok1->isAttributePure())
|
||||
return false;
|
||||
else if (tok1->function() && !tok1->function()->isConst && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
|
||||
else if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
|
||||
return false;
|
||||
}
|
||||
// templates/casts
|
||||
|
@ -105,7 +105,7 @@ bool isSameExpression(const Token *tok1, const Token *tok2, const std::set<std::
|
|||
|
||||
// non-const template function that is not a dynamic_cast => return false
|
||||
if (Token::simpleMatch(tok1->next()->link(), "> (") &&
|
||||
!(tok1->function() && tok1->function()->isConst) &&
|
||||
!(tok1->function() && tok1->function()->isConst()) &&
|
||||
tok1->str() != "dynamic_cast")
|
||||
return false;
|
||||
|
||||
|
@ -700,7 +700,7 @@ void CheckOther::checkRedundantAssignment()
|
|||
}
|
||||
} else if (scope->type == Scope::eSwitch) { // Avoid false positives if noreturn function is called in switch
|
||||
const Function* const func = tok->function();
|
||||
if (!func || !func->hasBody) {
|
||||
if (!func || !func->hasBody()) {
|
||||
varAssignments.clear();
|
||||
memAssignments.clear();
|
||||
continue;
|
||||
|
@ -2252,7 +2252,7 @@ void CheckOther::doubleCloseDirError(const Token *tok, const std::string &varnam
|
|||
namespace {
|
||||
bool notconst(const Function* func)
|
||||
{
|
||||
return !func->isConst;
|
||||
return !func->isConst();
|
||||
}
|
||||
|
||||
void getConstFunctions(const SymbolDatabase *symbolDatabase, std::list<const Function*> &constFunctions)
|
||||
|
|
|
@ -508,7 +508,7 @@ private:
|
|||
if (tok.next()->str() == ".") {
|
||||
if (Token::Match(&tok, "%var% . %var% (")) {
|
||||
const Function *function = tok.tokAt(2)->function();
|
||||
if (function && function->isStatic)
|
||||
if (function && function->isStatic())
|
||||
return &tok;
|
||||
}
|
||||
if (use_dead_pointer(checks, &tok)) {
|
||||
|
@ -1809,7 +1809,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all
|
|||
|
||||
if (pointer && Token::Match(vartok, "%var% . %var% (")) {
|
||||
const Function *function = vartok->tokAt(2)->function();
|
||||
return (!function || !function->isStatic);
|
||||
return (!function || !function->isStatic());
|
||||
}
|
||||
|
||||
if (cpp && Token::Match(vartok->next(), "<<|>>")) {
|
||||
|
|
|
@ -335,7 +335,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
|
||||
// operator function
|
||||
if (function.tokenDef->str().find("operator") == 0) {
|
||||
function.isOperator = true;
|
||||
function.isOperator(true);
|
||||
|
||||
// 'operator =' is special
|
||||
if (function.tokenDef->str() == "operator=")
|
||||
|
@ -374,7 +374,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
function.type = Function::eConstructor;
|
||||
|
||||
if (function.tokenDef->previous()->str() == "explicit")
|
||||
function.isExplicit = true;
|
||||
function.isExplicit(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok;
|
||||
|
@ -383,19 +383,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) {
|
||||
// virtual function
|
||||
if (tok1->previous()->str() == "virtual") {
|
||||
function.isVirtual = true;
|
||||
function.isVirtual(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// static function
|
||||
else if (tok1->previous()->str() == "static") {
|
||||
function.isStatic = true;
|
||||
function.isStatic(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// friend function
|
||||
else if (tok1->previous()->str() == "friend") {
|
||||
function.isFriend = true;
|
||||
function.isFriend(true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
|
||||
// const function
|
||||
if (end->next()->str() == "const")
|
||||
function.isConst = true;
|
||||
function.isConst(true);
|
||||
|
||||
// count the number of constructors
|
||||
if (function.isConstructor())
|
||||
|
@ -439,9 +439,9 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
// default or delete
|
||||
else if (Token::Match(end, ") = default|delete ;")) {
|
||||
if (end->strAt(2) == "default")
|
||||
function.isDefault = true;
|
||||
function.isDefault(true);
|
||||
else
|
||||
function.isDelete = true;
|
||||
function.isDelete(true);
|
||||
|
||||
tok = end->tokAt(3);
|
||||
|
||||
|
@ -453,7 +453,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
// const noexcept;
|
||||
// const noexcept = 0;
|
||||
else if (Token::Match(end, ") const| noexcept ;|=")) {
|
||||
function.isNoExcept = true;
|
||||
function.isNoExcept(true);
|
||||
|
||||
if (end->next()->str() == "const")
|
||||
tok = end->tokAt(3);
|
||||
|
@ -461,7 +461,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
tok = end->tokAt(2);
|
||||
|
||||
if (Token::Match(tok, "= %any% ;")) {
|
||||
function.isPure = true;
|
||||
function.isPure(true);
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
|
@ -481,10 +481,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
else
|
||||
tok = end->tokAt(2);
|
||||
|
||||
function.isNoExcept = tok->strAt(1) != "false";
|
||||
function.isNoExcept(tok->strAt(1) != "false");
|
||||
|
||||
if (Token::Match(tok->link()->next(), "= %any% ;")) {
|
||||
function.isPure = true;
|
||||
function.isPure(true);
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
|
@ -498,7 +498,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
else if (Token::Match(end, ") const| throw (") &&
|
||||
(end->next()->str() == "const" ? Token::Match(end->linkAt(3), ") ;|=") :
|
||||
Token::Match(end->linkAt(2), ") ;|="))) {
|
||||
function.isThrow = true;
|
||||
function.isThrow(true);
|
||||
|
||||
if (end->next()->str() == "const") {
|
||||
if (end->strAt(4) != ")")
|
||||
|
@ -511,7 +511,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
}
|
||||
|
||||
if (Token::Match(tok, "= %any% ;")) {
|
||||
function.isPure = true;
|
||||
function.isPure(true);
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
|
||||
// pure virtual function
|
||||
else if (Token::Match(end, ") const| = %any% ;")) {
|
||||
function.isPure = true;
|
||||
function.isPure(true);
|
||||
|
||||
if (end->next()->str() == "const")
|
||||
tok = end->tokAt(4);
|
||||
|
@ -538,8 +538,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
|
||||
// inline function
|
||||
else {
|
||||
function.isInline = true;
|
||||
function.hasBody = true;
|
||||
function.isInline(true);
|
||||
function.hasBody(true);
|
||||
|
||||
if (Token::Match(end, ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
|
@ -550,7 +550,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (end->strAt(arg) == "(")
|
||||
function.noexceptArg = end->tokAt(arg + 1);
|
||||
|
||||
function.isNoExcept = true;
|
||||
function.isNoExcept(true);
|
||||
} else if (Token::Match(end, ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
|
@ -560,7 +560,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (end->strAt(arg) != ")")
|
||||
function.throwArg = end->tokAt(arg);
|
||||
|
||||
function.isThrow = true;
|
||||
function.isThrow(true);
|
||||
}
|
||||
|
||||
// find start of function '{'
|
||||
|
@ -657,8 +657,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
else {
|
||||
Function* function = addGlobalFunction(scope, tok, argStart, funcStart);
|
||||
|
||||
if (!function)
|
||||
if (!function) {
|
||||
_tokenizer->syntaxError(tok);
|
||||
continue;
|
||||
}
|
||||
|
||||
// global functions can't be const but we have tests that are
|
||||
if (Token::Match(argStart->link(), ") const| noexcept")) {
|
||||
|
@ -670,7 +672,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (argStart->link()->strAt(arg) == "(")
|
||||
function->noexceptArg = argStart->link()->tokAt(arg + 1);
|
||||
|
||||
function->isNoExcept = true;
|
||||
function->isNoExcept(true);
|
||||
} else if (Token::Match(argStart->link(), ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
|
@ -680,7 +682,26 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (argStart->link()->strAt(arg) != ")")
|
||||
function->throwArg = argStart->link()->tokAt(arg);
|
||||
|
||||
function->isThrow = true;
|
||||
function->isThrow(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok->previous();
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1 && !Token::Match(tok1, ";|}|{")) {
|
||||
// static function
|
||||
if (tok1->str() == "static") {
|
||||
function->isStaticLocal(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// extern function
|
||||
else if (tok1->str() == "extern") {
|
||||
function->isExtern(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,7 +732,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (argStart->link()->strAt(arg) == "(")
|
||||
func->noexceptArg = argStart->link()->tokAt(arg + 1);
|
||||
|
||||
func->isNoExcept = true;
|
||||
func->isNoExcept(true);
|
||||
} else if (Token::Match(argStart->link(), ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
|
@ -721,7 +742,20 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (argStart->link()->strAt(arg) != ")")
|
||||
func->throwArg = argStart->link()->tokAt(arg);
|
||||
|
||||
func->isThrow = true;
|
||||
func->isThrow(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok->previous();
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1 && !Token::Match(tok1, ";|}|{")) {
|
||||
// extern function
|
||||
if (tok1->str() == "extern") {
|
||||
func->isExtern(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1548,7 +1582,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
|
|||
|
||||
function->arg = argStart;
|
||||
function->token = funcStart;
|
||||
function->hasBody = true;
|
||||
function->hasBody(true);
|
||||
|
||||
addNewFunction(&scope, &tok);
|
||||
|
||||
|
@ -1573,8 +1607,8 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok,
|
|||
// save the function name location
|
||||
function.tokenDef = funcStart;
|
||||
|
||||
function.isInline = false;
|
||||
function.hasBody = false;
|
||||
function.isInline(false);
|
||||
function.hasBody(false);
|
||||
function.type = Function::eFunction;
|
||||
function.nestedIn = scope;
|
||||
|
||||
|
@ -1585,7 +1619,7 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok,
|
|||
tok1 = tok1->previous();
|
||||
|
||||
// find the return type
|
||||
while (tok1 && Token::Match(tok1->next(), "static|const"))
|
||||
while (tok1 && Token::Match(tok1, "static|extern|const"))
|
||||
tok1 = tok1->next();
|
||||
|
||||
if (tok1)
|
||||
|
@ -1642,8 +1676,8 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
|||
if (it2->scope) {
|
||||
Function * func = findFunctionInScope(tok1, it2->scope);
|
||||
if (func) {
|
||||
if (!func->hasBody) {
|
||||
func->hasBody = true;
|
||||
if (!func->hasBody()) {
|
||||
func->hasBody(true);
|
||||
func->token = *tok;
|
||||
func->arg = argStart;
|
||||
addNewFunction(scope, tok);
|
||||
|
@ -1699,22 +1733,22 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
|||
if (match) {
|
||||
for (std::multimap<std::string, const Function *>::iterator it = scope1->functionMap.find((*tok)->str()); it != scope1->functionMap.end() && it->first == (*tok)->str(); ++it) {
|
||||
Function * func = const_cast<Function *>(it->second);
|
||||
if (!func->hasBody) {
|
||||
if (!func->hasBody()) {
|
||||
if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
||||
if (func->type == Function::eDestructor && destructor) {
|
||||
func->hasBody = true;
|
||||
func->hasBody(true);
|
||||
} else if (func->type != Function::eDestructor && !destructor) {
|
||||
// normal function?
|
||||
if ((*tok)->next()->link()) {
|
||||
const bool hasConstKeyword = (*tok)->next()->link()->next()->str() == "const";
|
||||
if ((func->isConst && hasConstKeyword) ||
|
||||
(!func->isConst && !hasConstKeyword)) {
|
||||
func->hasBody = true;
|
||||
if ((func->isConst() && hasConstKeyword) ||
|
||||
(!func->isConst() && !hasConstKeyword)) {
|
||||
func->hasBody(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (func->hasBody) {
|
||||
if (func->hasBody()) {
|
||||
func->token = *tok;
|
||||
func->arg = argStart;
|
||||
addNewFunction(scope, tok);
|
||||
|
@ -2072,19 +2106,21 @@ void SymbolDatabase::printOut(const char *title) const
|
|||
func->access == Protected ? "Protected" :
|
||||
func->access == Private ? "Private" :
|
||||
"???") << std::endl;
|
||||
std::cout << " hasBody: " << (func->hasBody ? "true" : "false") << std::endl;
|
||||
std::cout << " isInline: " << (func->isInline ? "true" : "false") << std::endl;
|
||||
std::cout << " isConst: " << (func->isConst ? "true" : "false") << std::endl;
|
||||
std::cout << " isVirtual: " << (func->isVirtual ? "true" : "false") << std::endl;
|
||||
std::cout << " isPure: " << (func->isPure ? "true" : "false") << std::endl;
|
||||
std::cout << " isStatic: " << (func->isStatic ? "true" : "false") << std::endl;
|
||||
std::cout << " isFriend: " << (func->isFriend ? "true" : "false") << std::endl;
|
||||
std::cout << " isExplicit: " << (func->isExplicit ? "true" : "false") << std::endl;
|
||||
std::cout << " isDefault: " << (func->isDefault ? "true" : "false") << std::endl;
|
||||
std::cout << " isDelete: " << (func->isDelete ? "true" : "false") << std::endl;
|
||||
std::cout << " isNoExcept: " << (func->isNoExcept ? "true" : "false") << std::endl;
|
||||
std::cout << " isThrow: " << (func->isThrow ? "true" : "false") << std::endl;
|
||||
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
|
||||
std::cout << " hasBody: " << (func->hasBody() ? "true" : "false") << std::endl;
|
||||
std::cout << " isInline: " << (func->isInline() ? "true" : "false") << std::endl;
|
||||
std::cout << " isConst: " << (func->isConst() ? "true" : "false") << std::endl;
|
||||
std::cout << " isVirtual: " << (func->isVirtual() ? "true" : "false") << std::endl;
|
||||
std::cout << " isPure: " << (func->isPure() ? "true" : "false") << std::endl;
|
||||
std::cout << " isStatic: " << (func->isStatic() ? "true" : "false") << std::endl;
|
||||
std::cout << " isStaticLocal: " << (func->isStaticLocal() ? "true" : "false") << std::endl;
|
||||
std::cout << " isExtern: " << (func->isExtern() ? "true" : "false") << std::endl;
|
||||
std::cout << " isFriend: " << (func->isFriend() ? "true" : "false") << std::endl;
|
||||
std::cout << " isExplicit: " << (func->isExplicit() ? "true" : "false") << std::endl;
|
||||
std::cout << " isDefault: " << (func->isDefault() ? "true" : "false") << std::endl;
|
||||
std::cout << " isDelete: " << (func->isDelete() ? "true" : "false") << std::endl;
|
||||
std::cout << " isNoExcept: " << (func->isNoExcept() ? "true" : "false") << std::endl;
|
||||
std::cout << " isThrow: " << (func->isThrow() ? "true" : "false") << std::endl;
|
||||
std::cout << " isOperator: " << (func->isOperator() ? "true" : "false") << std::endl;
|
||||
std::cout << " isAttributeConst: " << (func->isAttributeConst() ? "true" : "false") << std::endl;
|
||||
std::cout << " isAttributePure: " << (func->isAttributePure() ? "true" : "false") << std::endl;
|
||||
std::cout << " isAttributeNoreturn: " << (func->isAttributeNoreturn() ? "true" : "false") << std::endl;
|
||||
|
@ -2097,7 +2133,7 @@ void SymbolDatabase::printOut(const char *title) const
|
|||
if (!func->isConstructor() && !func->isDestructor())
|
||||
std::cout << " retDef: " << func->retDef->str() << " " <<_tokenizer->list.fileLine(func->retDef) << std::endl;
|
||||
std::cout << " retType: " << func->retType << std::endl;
|
||||
if (func->hasBody) {
|
||||
if (func->hasBody()) {
|
||||
std::cout << " token: " << _tokenizer->list.fileLine(func->token) << std::endl;
|
||||
std::cout << " arg: " << _tokenizer->list.fileLine(func->arg) << std::endl;
|
||||
}
|
||||
|
@ -2394,7 +2430,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
|||
nameTok = tok->previous();
|
||||
endTok = nameTok->previous();
|
||||
|
||||
if (hasBody)
|
||||
if (hasBody())
|
||||
symbolDatabase->debugMessage(nameTok, "Function::addArguments found argument \'" + nameTok->str() + "\' with varid 0.");
|
||||
} else
|
||||
endTok = startTok;
|
||||
|
@ -2449,7 +2485,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
|||
|
||||
bool Function::isImplicitlyVirtual(bool defaultVal) const
|
||||
{
|
||||
if (isVirtual)
|
||||
if (isVirtual())
|
||||
return true;
|
||||
else if (access == Private || access == Public || access == Protected) {
|
||||
bool safe = true;
|
||||
|
@ -2476,7 +2512,7 @@ bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const
|
|||
// check if function defined in base class
|
||||
for (std::multimap<std::string, const Function *>::const_iterator it = parent->functionMap.find(tokenDef->str()); it != parent->functionMap.end() && it->first == tokenDef->str(); ++it) {
|
||||
const Function * func = it->second;
|
||||
if (func->isVirtual) { // Base is virtual and of same name
|
||||
if (func->isVirtual()) { // Base is virtual and of same name
|
||||
const Token *temp1 = func->tokenDef->previous();
|
||||
const Token *temp2 = tokenDef->previous();
|
||||
bool returnMatch = true;
|
||||
|
@ -3104,7 +3140,7 @@ const Function* Scope::findFunction(const Token *tok) const
|
|||
// check if this function is a member function
|
||||
if (scope && scope->functionOf && scope->functionOf->isClassOrStruct()) {
|
||||
// check if isConst match
|
||||
if (scope->function && scope->function->isConst == func->isConst)
|
||||
if (scope->function && scope->function->isConst() == func->isConst())
|
||||
return func;
|
||||
} else
|
||||
return func;
|
||||
|
|
|
@ -557,6 +557,43 @@ private:
|
|||
};
|
||||
|
||||
class CPPCHECKLIB Function {
|
||||
/** @brief flags mask used to access specific bit. */
|
||||
enum {
|
||||
fHasBody = (1 << 0), /** @brief has implementation */
|
||||
fIsInline = (1 << 1), /** @brief implementation in class definition */
|
||||
fIsConst = (1 << 2), /** @brief is const */
|
||||
fIsVirtual = (1 << 3), /** @brief is virtual */
|
||||
fIsPure = (1 << 4), /** @brief is pure virtual */
|
||||
fIsStatic = (1 << 5), /** @brief is static */
|
||||
fIsStaticLocal = (1 << 6), /** @brief is static local */
|
||||
fIsExtern = (1 << 7), /** @brief is extern */
|
||||
fIsFriend = (1 << 8), /** @brief is friend */
|
||||
fIsExplicit = (1 << 9), /** @brief is explicit */
|
||||
fIsDefault = (1 << 10), /** @brief is default */
|
||||
fIsDelete = (1 << 11), /** @brief is delete */
|
||||
fIsNoExcept = (1 << 12), /** @brief is noexcept */
|
||||
fIsThrow = (1 << 13), /** @brief is throw */
|
||||
fIsOperator = (1 << 14) /** @brief is operator */
|
||||
};
|
||||
|
||||
/**
|
||||
* Get specified flag state.
|
||||
* @param flag flag to get state of
|
||||
* @return true if flag set or false in flag not set
|
||||
*/
|
||||
bool getFlag(int flag) const {
|
||||
return bool((flags & flag) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set specified flag state.
|
||||
* @param flag flag to set state
|
||||
* @param state new state of flag
|
||||
*/
|
||||
void setFlag(int flag, bool state) {
|
||||
flags = state ? flags | flag : flags & ~flag;
|
||||
}
|
||||
|
||||
public:
|
||||
enum Type { eConstructor, eCopyConstructor, eMoveConstructor, eOperatorEqual, eDestructor, eFunction };
|
||||
|
||||
|
@ -572,21 +609,9 @@ public:
|
|||
initArgCount(0),
|
||||
type(eFunction),
|
||||
access(Public),
|
||||
hasBody(false),
|
||||
isInline(false),
|
||||
isConst(false),
|
||||
isVirtual(false),
|
||||
isPure(false),
|
||||
isStatic(false),
|
||||
isFriend(false),
|
||||
isExplicit(false),
|
||||
isDefault(false),
|
||||
isDelete(false),
|
||||
isNoExcept(false),
|
||||
isThrow(false),
|
||||
isOperator(false),
|
||||
noexceptArg(nullptr),
|
||||
throwArg(nullptr) {
|
||||
throwArg(nullptr),
|
||||
flags(0) {
|
||||
}
|
||||
|
||||
const std::string &name() const {
|
||||
|
@ -638,6 +663,98 @@ public:
|
|||
return tokenDef->isDeclspecNothrow();
|
||||
}
|
||||
|
||||
bool hasBody() const {
|
||||
return getFlag(fHasBody);
|
||||
}
|
||||
bool isInline() const {
|
||||
return getFlag(fIsInline);
|
||||
}
|
||||
bool isConst() const {
|
||||
return getFlag(fIsConst);
|
||||
}
|
||||
bool isVirtual() const {
|
||||
return getFlag(fIsVirtual);
|
||||
}
|
||||
bool isPure() const {
|
||||
return getFlag(fIsPure);
|
||||
}
|
||||
bool isStatic() const {
|
||||
return getFlag(fIsStatic);
|
||||
}
|
||||
bool isStaticLocal() const {
|
||||
return getFlag(fIsStaticLocal);
|
||||
}
|
||||
bool isExtern() const {
|
||||
return getFlag(fIsExtern);
|
||||
}
|
||||
bool isFriend() const {
|
||||
return getFlag(fIsFriend);
|
||||
}
|
||||
bool isExplicit() const {
|
||||
return getFlag(fIsExplicit);
|
||||
}
|
||||
bool isDefault() const {
|
||||
return getFlag(fIsDefault);
|
||||
}
|
||||
bool isDelete() const {
|
||||
return getFlag(fIsDelete);
|
||||
}
|
||||
bool isNoExcept() const {
|
||||
return getFlag(fIsNoExcept);
|
||||
}
|
||||
bool isThrow() const {
|
||||
return getFlag(fIsThrow);
|
||||
}
|
||||
bool isOperator() const {
|
||||
return getFlag(fIsOperator);
|
||||
}
|
||||
|
||||
void hasBody(bool state) {
|
||||
setFlag(fHasBody, state);
|
||||
}
|
||||
void isInline(bool state) {
|
||||
setFlag(fIsInline, state);
|
||||
}
|
||||
void isConst(bool state) {
|
||||
setFlag(fIsConst, state);
|
||||
}
|
||||
void isVirtual(bool state) {
|
||||
setFlag(fIsVirtual, state);
|
||||
}
|
||||
void isPure(bool state) {
|
||||
setFlag(fIsPure, state);
|
||||
}
|
||||
void isStatic(bool state) {
|
||||
setFlag(fIsStatic, state);
|
||||
}
|
||||
void isStaticLocal(bool state) {
|
||||
setFlag(fIsStaticLocal, state);
|
||||
}
|
||||
void isExtern(bool state) {
|
||||
setFlag(fIsExtern, state);
|
||||
}
|
||||
void isFriend(bool state) {
|
||||
setFlag(fIsFriend, state);
|
||||
}
|
||||
void isExplicit(bool state) {
|
||||
setFlag(fIsExplicit, state);
|
||||
}
|
||||
void isDefault(bool state) {
|
||||
setFlag(fIsDefault, state);
|
||||
}
|
||||
void isDelete(bool state) {
|
||||
setFlag(fIsDelete, state);
|
||||
}
|
||||
void isNoExcept(bool state) {
|
||||
setFlag(fIsNoExcept, state);
|
||||
}
|
||||
void isThrow(bool state) {
|
||||
setFlag(fIsThrow, state);
|
||||
}
|
||||
void isOperator(bool state) {
|
||||
setFlag(fIsOperator, state);
|
||||
}
|
||||
|
||||
const Token *tokenDef; // function name token in class definition
|
||||
const Token *argDef; // function argument start '(' in class definition
|
||||
const Token *token; // function name token in implementation
|
||||
|
@ -650,19 +767,6 @@ public:
|
|||
unsigned int initArgCount; // number of args with default values
|
||||
Type type; // constructor, destructor, ...
|
||||
AccessControl access; // public/protected/private
|
||||
bool hasBody; // has implementation
|
||||
bool isInline; // implementation in class definition
|
||||
bool isConst; // is const
|
||||
bool isVirtual; // is virtual
|
||||
bool isPure; // is pure virtual
|
||||
bool isStatic; // is static
|
||||
bool isFriend; // is friend
|
||||
bool isExplicit; // is explicit
|
||||
bool isDefault; // is default
|
||||
bool isDelete; // is delete
|
||||
bool isNoExcept; // is noexcept
|
||||
bool isThrow; // is throw
|
||||
bool isOperator; // is operator
|
||||
const Token *noexceptArg;
|
||||
const Token *throwArg;
|
||||
|
||||
|
@ -670,6 +774,8 @@ public:
|
|||
|
||||
private:
|
||||
bool isImplicitlyVirtual_rec(const ::Type* type, bool& safe) const;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
class CPPCHECKLIB Scope {
|
||||
|
|
|
@ -148,6 +148,7 @@ private:
|
|||
TEST_CASE(memberFunctionOfUnknownClassMacro1);
|
||||
TEST_CASE(memberFunctionOfUnknownClassMacro2);
|
||||
TEST_CASE(memberFunctionOfUnknownClassMacro3);
|
||||
TEST_CASE(functionLinkage);
|
||||
|
||||
TEST_CASE(classWithFriend);
|
||||
|
||||
|
@ -764,7 +765,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == tokenizer.tokens()->next());
|
||||
ASSERT(function && function->hasBody);
|
||||
ASSERT(function && function->hasBody());
|
||||
ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn != scope);
|
||||
ASSERT(function && function->retDef == tokenizer.tokens());
|
||||
}
|
||||
|
@ -788,7 +789,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && function->hasBody && function->isInline);
|
||||
ASSERT(function && function->hasBody() && function->isInline());
|
||||
ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
|
||||
ASSERT(function && function->retDef == functionToken->previous());
|
||||
|
||||
|
@ -813,7 +814,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && !function->hasBody);
|
||||
ASSERT(function && !function->hasBody());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,7 +836,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && function->hasBody && !function->isInline);
|
||||
ASSERT(function && function->hasBody() && !function->isInline());
|
||||
ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
|
||||
}
|
||||
}
|
||||
|
@ -857,7 +858,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && function->hasBody);
|
||||
ASSERT(function && function->hasBody());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -878,7 +879,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && function->hasBody && function->isInline);
|
||||
ASSERT(function && function->hasBody() && function->isInline());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -899,7 +900,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && !function->hasBody);
|
||||
ASSERT(function && !function->hasBody());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,7 +921,7 @@ private:
|
|||
|
||||
ASSERT(function && function->token->str() == "func");
|
||||
ASSERT(function && function->token == functionToken);
|
||||
ASSERT(function && function->hasBody && !function->isInline);
|
||||
ASSERT(function && function->hasBody() && !function->isInline());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -977,7 +978,7 @@ private:
|
|||
for (std::list<Scope>::const_iterator scope = db->scopeList.begin(); scope != db->scopeList.end(); ++scope) {
|
||||
for (std::list<Function>::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
|
||||
ASSERT_EQUALS("Sub", func->token->str());
|
||||
ASSERT_EQUALS(true, func->hasBody);
|
||||
ASSERT_EQUALS(true, func->hasBody());
|
||||
ASSERT_EQUALS(Function::eConstructor, func->type);
|
||||
seen_something = true;
|
||||
}
|
||||
|
@ -990,13 +991,13 @@ private:
|
|||
{
|
||||
GET_SYMBOL_DB("class Foo { Foo(Foo f); };");
|
||||
const Function* ctor = tokenizer.tokens()->tokAt(3)->function();
|
||||
ASSERT(db && ctor && ctor->type == Function::eConstructor && !ctor->isExplicit);
|
||||
ASSERT(db && ctor && ctor->type == Function::eConstructor && !ctor->isExplicit());
|
||||
ASSERT(ctor && ctor->retDef == 0);
|
||||
}
|
||||
{
|
||||
GET_SYMBOL_DB("class Foo { explicit Foo(Foo f); };");
|
||||
const Function* ctor = tokenizer.tokens()->tokAt(4)->function();
|
||||
ASSERT(db && ctor && ctor->type == Function::eConstructor && ctor->isExplicit);
|
||||
ASSERT(db && ctor && ctor->type == Function::eConstructor && ctor->isExplicit());
|
||||
ASSERT(ctor && ctor->retDef == 0);
|
||||
}
|
||||
{
|
||||
|
@ -1027,7 +1028,7 @@ private:
|
|||
const Function *foo = &scope->functionList.front();
|
||||
|
||||
ASSERT(foo && foo->token->str() == "foo");
|
||||
ASSERT(foo && foo->hasBody);
|
||||
ASSERT(foo && foo->hasBody());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1046,12 +1047,12 @@ private:
|
|||
const Function *foo_int = &scope->functionList.back();
|
||||
|
||||
ASSERT(foo && foo->token->str() == "foo");
|
||||
ASSERT(foo && foo->hasBody);
|
||||
ASSERT(foo && foo->hasBody());
|
||||
ASSERT(foo && foo->token->strAt(2) == ")");
|
||||
|
||||
ASSERT(foo_int && !foo_int->token);
|
||||
ASSERT(foo_int && foo_int->tokenDef->str() == "foo");
|
||||
ASSERT(foo_int && !foo_int->hasBody);
|
||||
ASSERT(foo_int && !foo_int->hasBody());
|
||||
ASSERT(foo_int && foo_int->tokenDef->strAt(2) == "int");
|
||||
|
||||
ASSERT(&foo_int->argumentList.front() == db->getVariableFromVarId(1));
|
||||
|
@ -1123,6 +1124,37 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void functionLinkage() {
|
||||
GET_SYMBOL_DB("static void f1() { }\n"
|
||||
"void f2();\n"
|
||||
"extern void f3();\n"
|
||||
"void f4();\n"
|
||||
"extern void f5() { };\n"
|
||||
"void f6() { }");
|
||||
|
||||
ASSERT(db && errout.str() == "");
|
||||
|
||||
if (db) {
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "f1");
|
||||
ASSERT(f && f->function() && f->function()->isStaticLocal());
|
||||
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "f2");
|
||||
ASSERT(f && f->function() && !f->function()->isStaticLocal());
|
||||
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "f3");
|
||||
ASSERT(f && f->function() && f->function()->isExtern());
|
||||
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "f4");
|
||||
ASSERT(f && f->function() && !f->function()->isExtern());
|
||||
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "f5");
|
||||
ASSERT(f && f->function() && f->function()->isExtern());
|
||||
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "f6");
|
||||
ASSERT(f && f->function() && !f->function()->isExtern());
|
||||
}
|
||||
}
|
||||
|
||||
void classWithFriend() {
|
||||
GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };")
|
||||
// 3 scopes: Global, 3 classes
|
||||
|
@ -1373,7 +1405,7 @@ private:
|
|||
// The class has a constructor but the implementation _is not_ seen
|
||||
ASSERT_EQUALS(1U, scope->functionList.size());
|
||||
const Function *function = &(scope->functionList.front());
|
||||
ASSERT_EQUALS(false, function->hasBody);
|
||||
ASSERT_EQUALS(false, function->hasBody());
|
||||
}
|
||||
|
||||
// based on namespaces1 but here the namespaces match
|
||||
|
@ -1408,7 +1440,7 @@ private:
|
|||
ASSERT_EQUALS(1U, scope->functionList.size());
|
||||
const Function *function = &(scope->functionList.front());
|
||||
ASSERT_EQUALS("X", function->tokenDef->str());
|
||||
ASSERT_EQUALS(true, function->hasBody);
|
||||
ASSERT_EQUALS(true, function->hasBody());
|
||||
}
|
||||
|
||||
void namespaces3() { // #3854 - namespace with unknown macro
|
||||
|
@ -1915,7 +1947,7 @@ private:
|
|||
|
||||
void symboldatabase41() { // ticket #5197 (unknown macro)
|
||||
GET_SYMBOL_DB("struct X1 { MACRO1 f(int spd) MACRO2; };\n");
|
||||
ASSERT(db && db->findScopeByName("X1") && db->findScopeByName("X1")->functionList.size() == 1 && !db->findScopeByName("X1")->functionList.front().hasBody);
|
||||
ASSERT(db && db->findScopeByName("X1") && db->findScopeByName("X1")->functionList.size() == 1 && !db->findScopeByName("X1")->functionList.front().hasBody());
|
||||
}
|
||||
|
||||
void symboldatabase42() { // only put variables in variable list
|
||||
|
@ -2379,7 +2411,7 @@ private:
|
|||
|
||||
#define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
|
||||
ASSERT_EQUALS(true, x != nullptr); \
|
||||
if (x) ASSERT_EQUALS(true, x->isNoExcept);
|
||||
if (x) ASSERT_EQUALS(true, x->isNoExcept());
|
||||
|
||||
void noexceptFunction1() {
|
||||
GET_SYMBOL_DB("void func1() noexcept;\n"
|
||||
|
@ -2410,7 +2442,7 @@ private:
|
|||
|
||||
#define CLASS_FUNC(x, y, z) const Function *x = findFunctionByName(#x, y); \
|
||||
ASSERT_EQUALS(true, x != nullptr); \
|
||||
if (x) ASSERT_EQUALS(z, x->isNoExcept);
|
||||
if (x) ASSERT_EQUALS(z, x->isNoExcept());
|
||||
|
||||
void noexceptFunction3() {
|
||||
GET_SYMBOL_DB("struct Fred {\n"
|
||||
|
@ -2478,7 +2510,7 @@ private:
|
|||
|
||||
#define FUNC_THROW(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
|
||||
ASSERT_EQUALS(true, x != nullptr); \
|
||||
if (x) ASSERT_EQUALS(true, x->isThrow);
|
||||
if (x) ASSERT_EQUALS(true, x->isThrow());
|
||||
|
||||
void throwFunction1() {
|
||||
GET_SYMBOL_DB("void func1() throw();\n"
|
||||
|
@ -2498,7 +2530,7 @@ private:
|
|||
|
||||
#define CLASS_FUNC_THROW(x, y) const Function *x = findFunctionByName(#x, y); \
|
||||
ASSERT_EQUALS(true, x != nullptr); \
|
||||
if (x) ASSERT_EQUALS(true, x->isThrow);
|
||||
if (x) ASSERT_EQUALS(true, x->isThrow());
|
||||
void throwFunction2() {
|
||||
GET_SYMBOL_DB("struct Fred {\n"
|
||||
" void func1() throw();\n"
|
||||
|
|
Loading…
Reference in New Issue