This commit is contained in:
parent
25ada657da
commit
fde5994cc3
|
@ -1903,7 +1903,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const
|
|||
const Type *derivedFrom = i.type;
|
||||
|
||||
// find the function in the base class
|
||||
if (derivedFrom && derivedFrom->classScope) {
|
||||
if (derivedFrom && derivedFrom->classScope && derivedFrom->classScope != scope) {
|
||||
if (isMemberVar(derivedFrom->classScope, tok))
|
||||
return true;
|
||||
}
|
||||
|
@ -1944,7 +1944,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
|
|||
const Type *derivedFrom = i.type;
|
||||
|
||||
// find the function in the base class
|
||||
if (derivedFrom && derivedFrom->classScope) {
|
||||
if (derivedFrom && derivedFrom->classScope && derivedFrom->classScope != scope) {
|
||||
if (isMemberFunc(derivedFrom->classScope, tok))
|
||||
return true;
|
||||
}
|
||||
|
@ -2460,7 +2460,8 @@ void CheckClass::checkDuplInheritedMembersRecursive(const Type* typeCurrent, con
|
|||
}
|
||||
}
|
||||
}
|
||||
checkDuplInheritedMembersRecursive(typeCurrent, parentClassIt.type);
|
||||
if (typeCurrent != parentClassIt.type)
|
||||
checkDuplInheritedMembersRecursive(typeCurrent, parentClassIt.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ double MathLib::toDoubleNumber(const std::string &str)
|
|||
return ret;
|
||||
}
|
||||
|
||||
template<> std::string MathLib::toString(double value)
|
||||
template<> std::string MathLib::toString<double>(double value)
|
||||
{
|
||||
std::ostringstream result;
|
||||
result.precision(12);
|
||||
|
|
|
@ -159,7 +159,7 @@ MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2);
|
|||
MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2);
|
||||
MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2);
|
||||
|
||||
template<> CPPCHECKLIB std::string MathLib::toString(double value); // Declare specialization to avoid linker problems
|
||||
template<> CPPCHECKLIB std::string MathLib::toString<double>(double value); // Declare specialization to avoid linker problems
|
||||
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -633,7 +633,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
|
||||
bool newFunc = true; // Is this function already in the database?
|
||||
for (std::multimap<std::string, const Function *>::const_iterator i = scope->functionMap.find(tok->str()); i != scope->functionMap.end() && i->first == tok->str(); ++i) {
|
||||
if (Function::argsMatch(scope, i->second->argDef, argStart, emptyString, 0)) {
|
||||
if (i->second->argsMatch(scope, i->second->argDef, argStart, emptyString, 0)) {
|
||||
newFunc = false;
|
||||
break;
|
||||
}
|
||||
|
@ -2348,7 +2348,39 @@ static bool usingNamespace(const Scope *scope, const Token *first, const Token *
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length)
|
||||
static bool typesMatch(
|
||||
const Scope *first_scope,
|
||||
const Token *first_token,
|
||||
const Scope *second_scope,
|
||||
const Token *second_token,
|
||||
const Token **new_first,
|
||||
const Token **new_second)
|
||||
{
|
||||
// get first type
|
||||
const Type * first_type = first_scope->check->findType(first_token, first_scope);
|
||||
if (first_type) {
|
||||
// get second type
|
||||
const Type * second_type = second_scope->check->findType(second_token, second_scope);
|
||||
// check if types match
|
||||
if (first_type == second_type) {
|
||||
const Token* tok1 = first_token;
|
||||
while (tok1 && tok1->str() != first_type->name())
|
||||
tok1 = tok1->next();
|
||||
const Token *tok2 = second_token;
|
||||
while (tok2 && tok2->str() != second_type->name())
|
||||
tok2 = tok2->next();
|
||||
// update parser token positions
|
||||
if (tok1 && tok2) {
|
||||
*new_first = tok1;
|
||||
*new_second = tok2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length) const
|
||||
{
|
||||
const bool isCPP = scope->check->isCPP();
|
||||
if (!isCPP) // C does not support overloads
|
||||
|
@ -2485,6 +2517,10 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
|
|||
else if (usingNamespace(scope, first->next(), second->next(), offset))
|
||||
first = first->tokAt(offset);
|
||||
|
||||
// same type with different qualification
|
||||
else if (typesMatch(scope, first->next(), nestedIn, second->next(), &first, &second))
|
||||
;
|
||||
|
||||
// variable with class path
|
||||
else if (arg_path_length && Token::Match(first->next(), "%name%") && first->strAt(1) != "const") {
|
||||
std::string param = path;
|
||||
|
@ -2641,7 +2677,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
|
|||
const Function *f = i->second;
|
||||
if (f->hasBody())
|
||||
continue;
|
||||
if (Function::argsMatch(scope, f->argDef, argStart, emptyString, 0)) {
|
||||
if (f->argsMatch(scope, f->argDef, argStart, emptyString, 0)) {
|
||||
function = const_cast<Function *>(i->second);
|
||||
break;
|
||||
}
|
||||
|
@ -2793,7 +2829,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
|||
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 (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
||||
if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
||||
if (func->type == Function::eDestructor && destructor) {
|
||||
func->hasBody(true);
|
||||
} else if (func->type != Function::eDestructor && !destructor) {
|
||||
|
@ -2975,6 +3011,8 @@ const Token *Type::initBaseInfo(const Token *tok, const Token *tok1)
|
|||
}
|
||||
}
|
||||
|
||||
base.type = classScope->check->findType(base.nameTok, classScope);
|
||||
|
||||
// save pattern for base class name
|
||||
derivedFrom.push_back(base);
|
||||
} else
|
||||
|
@ -4482,6 +4520,8 @@ const Type* SymbolDatabase::findVariableTypeInBase(const Scope* scope, const Tok
|
|||
for (const Type::BaseInfo & i : derivedFrom) {
|
||||
const Type *base = i.type;
|
||||
if (base && base->classScope) {
|
||||
if (base->classScope == scope)
|
||||
return nullptr;
|
||||
const Type * type = base->classScope->findType(typeTok->str());
|
||||
if (type)
|
||||
return type;
|
||||
|
@ -4650,6 +4690,30 @@ void Scope::findFunctionInBase(const std::string & name, nonneg int args, std::v
|
|||
}
|
||||
}
|
||||
|
||||
const Scope *Scope::findRecordInBase(const std::string & name) const
|
||||
{
|
||||
if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) {
|
||||
const std::vector<Type::BaseInfo> &derivedFrom = definedType->derivedFrom;
|
||||
for (const Type::BaseInfo & i : derivedFrom) {
|
||||
const Type *base = i.type;
|
||||
if (base && base->classScope) {
|
||||
if (base->classScope == this) // Recursive class; tok should have been found already
|
||||
continue;
|
||||
|
||||
if (base->name() == name) {
|
||||
return base->classScope;
|
||||
}
|
||||
|
||||
const ::Type * type = base->classScope->findType(name);
|
||||
if (type)
|
||||
return type->classScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void checkVariableCallMatch(const Variable* callarg, const Variable* funcarg, size_t& same, size_t& fallback1, size_t& fallback2)
|
||||
|
@ -5219,9 +5283,14 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
|
|||
}
|
||||
} else {
|
||||
const Type * type = scope->findType(tok->str());
|
||||
const Scope *scope1;
|
||||
if (type)
|
||||
return type;
|
||||
else
|
||||
else if ((scope1 = scope->findRecordInBase(tok->str()))) {
|
||||
type = scope1->definedType;
|
||||
if (type)
|
||||
return type;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5251,9 +5320,14 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
|
|||
}
|
||||
} else {
|
||||
const Type * type = scope->findType(tok->str());
|
||||
const Scope *scope1;
|
||||
if (type)
|
||||
return type;
|
||||
else
|
||||
else if ((scope1 = scope->findRecordInBase(tok->str()))) {
|
||||
type = scope1->definedType;
|
||||
if (type)
|
||||
return type;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5345,7 +5419,7 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
|
|||
for (std::multimap<std::string, const Function *>::const_iterator it = ns->functionMap.find(func->str());
|
||||
it != ns->functionMap.end() && it->first == func->str(); ++it) {
|
||||
|
||||
if (Function::argsMatch(ns, it->second->argDef, func->next(), path, path_length) &&
|
||||
if (it->second->argsMatch(ns, it->second->argDef, func->next(), path, path_length) &&
|
||||
it->second->isDestructor() == destructor) {
|
||||
function = it->second;
|
||||
break;
|
||||
|
|
|
@ -895,7 +895,7 @@ public:
|
|||
const Token *templateDef; ///< points to 'template <' before function
|
||||
const Token *functionPointerUsage; ///< function pointer usage
|
||||
|
||||
static bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length);
|
||||
bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length) const;
|
||||
|
||||
static bool returnsReference(const Function* function, bool unknown = false);
|
||||
|
||||
|
@ -1150,6 +1150,8 @@ public:
|
|||
|
||||
const Token * addEnum(const Token * tok, bool isCpp);
|
||||
|
||||
const Scope *findRecordInBase(const std::string &name) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief helper function for getVariableList()
|
||||
|
|
|
@ -5391,14 +5391,14 @@ private:
|
|||
"int MixerParticipant::GetAudioFrame() {\n"
|
||||
" return 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::GetAudioFrame' can be static (but you may consider moving to unnamed namespace).\n", errout.str());
|
||||
|
||||
checkConst("class MixerParticipant : public MixerParticipant {\n"
|
||||
" bool InitializeFileReader() {\n"
|
||||
" printf(\"music\");\n"
|
||||
" }\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::InitializeFileReader' can be static (but you may consider moving to unnamed namespace).\n", errout.str());
|
||||
|
||||
// Based on an example from SVN source code causing an endless recursion within CheckClass::isConstMemberFunc()
|
||||
// A more complete example including a template declaration like
|
||||
|
|
|
@ -398,6 +398,7 @@ private:
|
|||
TEST_CASE(findFunction31);
|
||||
TEST_CASE(findFunction32); // C: relax type matching
|
||||
TEST_CASE(findFunction33); // #9885 variadic function
|
||||
TEST_CASE(findFunction34); // #10061
|
||||
TEST_CASE(findFunctionContainer);
|
||||
TEST_CASE(findFunctionExternC);
|
||||
TEST_CASE(findFunctionGlobalScope); // ::foo
|
||||
|
@ -6217,6 +6218,26 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void findFunction34() {
|
||||
GET_SYMBOL_DB("namespace cppcheck {\n"
|
||||
" class Platform {\n"
|
||||
" public:\n"
|
||||
" enum PlatformType { Unspecified };\n"
|
||||
" };\n"
|
||||
"}\n"
|
||||
"class ImportProject {\n"
|
||||
" void selectOneVsConfig(cppcheck::Platform::PlatformType);\n"
|
||||
"};\n"
|
||||
"class Settings : public cppcheck::Platform { };\n"
|
||||
"void ImportProject::selectOneVsConfig(Settings::PlatformType) { }");
|
||||
(void)db;
|
||||
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "selectOneVsConfig ( Settings :: PlatformType ) { }");
|
||||
ASSERT(foo);
|
||||
ASSERT(foo->function());
|
||||
ASSERT(foo->function()->tokenDef);
|
||||
ASSERT_EQUALS(8, foo->function()->tokenDef->linenr());
|
||||
}
|
||||
|
||||
void findFunctionContainer() {
|
||||
{
|
||||
GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n"
|
||||
|
|
Loading…
Reference in New Issue