Fixed #4458 (False positive: noCopyConstructor in template class)
This commit is contained in:
parent
d5dfd5a006
commit
d37906041b
|
@ -61,10 +61,6 @@ void CheckClass::constructors()
|
||||||
if (scope->isForwardDeclaration())
|
if (scope->isForwardDeclaration())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// don't check uninstantiated template classes
|
|
||||||
if (scope->classDef->strAt(-1) == ">")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// There are no constructors.
|
// There are no constructors.
|
||||||
if (scope->numConstructors == 0) {
|
if (scope->numConstructors == 0) {
|
||||||
// If there is a private variable, there should be a constructor..
|
// If there is a private variable, there should be a constructor..
|
||||||
|
|
|
@ -320,14 +320,26 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
function.type = Function::eDestructor;
|
function.type = Function::eDestructor;
|
||||||
|
|
||||||
// copy constructor
|
// copy constructor
|
||||||
else if ((Token::Match(function.tokenDef, "%var% ( const %var% & )") ||
|
else if ((Token::Match(function.tokenDef, "%var% ( const %var% & %var%| )") ||
|
||||||
Token::Match(function.tokenDef, "%var% ( const %var% & %var% )")) &&
|
(Token::Match(function.tokenDef, "%var% ( const %var% <") &&
|
||||||
|
Token::Match(function.tokenDef->linkAt(4), "> & %var%| )"))) &&
|
||||||
function.tokenDef->strAt(3) == scope->className)
|
function.tokenDef->strAt(3) == scope->className)
|
||||||
function.type = Function::eCopyConstructor;
|
function.type = Function::eCopyConstructor;
|
||||||
|
|
||||||
|
else if ((Token::Match(function.tokenDef, "%var% <") &&
|
||||||
|
Token::Match(function.tokenDef->linkAt(1), "> (const %var% & %var%| )")) &&
|
||||||
|
function.tokenDef->linkAt(1)->strAt(3) == scope->className)
|
||||||
|
function.type = Function::eCopyConstructor;
|
||||||
|
|
||||||
// copy constructor with non-const argument
|
// copy constructor with non-const argument
|
||||||
else if ((Token::Match(function.tokenDef, "%var% ( %var% & )") ||
|
else if ((Token::Match(function.tokenDef, "%var% ( %var% & %var%| )") ||
|
||||||
Token::Match(function.tokenDef, "%var% ( %var% & %var% )")) &&
|
(Token::Match(function.tokenDef, "%var% ( %var% <") &&
|
||||||
|
Token::Match(function.tokenDef->linkAt(4), "> & %var%| )"))) &&
|
||||||
|
function.tokenDef->strAt(2) == scope->className)
|
||||||
|
function.type = Function::eCopyConstructor;
|
||||||
|
|
||||||
|
else if ((Token::Match(function.tokenDef, "%var% <") &&
|
||||||
|
Token::Match(function.tokenDef->linkAt(1), "> ( %var% & %var%| )")) &&
|
||||||
function.tokenDef->strAt(2) == scope->className)
|
function.tokenDef->strAt(2) == scope->className)
|
||||||
function.type = Function::eCopyConstructor;
|
function.type = Function::eCopyConstructor;
|
||||||
|
|
||||||
|
@ -929,6 +941,15 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template constructor?
|
||||||
|
else if (Token::Match(tok, "%var% <") && Token::Match(tok->next()->link(), "> (") &&
|
||||||
|
(Token::Match(tok->next()->link()->next()->link(), ") const| ;|{|=") ||
|
||||||
|
Token::Match(tok->next()->link()->next()->link(), ") : ::| %var% (|::|<|{"))) {
|
||||||
|
*funcStart = tok;
|
||||||
|
*argStart = tok->next()->link()->next();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,8 @@ private:
|
||||||
TEST_CASE(virtualDestructorInherited);
|
TEST_CASE(virtualDestructorInherited);
|
||||||
TEST_CASE(virtualDestructorTemplate);
|
TEST_CASE(virtualDestructorTemplate);
|
||||||
|
|
||||||
TEST_CASE(copyConstructor);
|
TEST_CASE(copyConstructor1);
|
||||||
|
TEST_CASE(copyConstructor2); // ticket #4458
|
||||||
|
|
||||||
TEST_CASE(noConstructor1);
|
TEST_CASE(noConstructor1);
|
||||||
TEST_CASE(noConstructor2);
|
TEST_CASE(noConstructor2);
|
||||||
|
@ -186,7 +187,7 @@ private:
|
||||||
checkClass.copyconstructors();
|
checkClass.copyconstructors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyConstructor() {
|
void copyConstructor1() {
|
||||||
checkCopyConstructor("class F\n"
|
checkCopyConstructor("class F\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" public:\n"
|
" public:\n"
|
||||||
|
@ -382,6 +383,22 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void copyConstructor2() { // ticket #4458
|
||||||
|
checkCopyConstructor("template <class _Tp>\n"
|
||||||
|
"class Vector\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" Vector() {\n"
|
||||||
|
" _M_finish = new _Tp[ 42 ];\n"
|
||||||
|
" }\n"
|
||||||
|
" Vector( const Vector<_Tp>& v ) {\n"
|
||||||
|
" }\n"
|
||||||
|
" _Tp* _M_finish;\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check the operator Equal
|
// Check the operator Equal
|
||||||
void checkOpertorEq(const char code[]) {
|
void checkOpertorEq(const char code[]) {
|
||||||
// Clear the error log
|
// Clear the error log
|
||||||
|
|
|
@ -277,10 +277,29 @@ private:
|
||||||
void simple6() { // ticket #4085 - uninstantiated template class
|
void simple6() { // ticket #4085 - uninstantiated template class
|
||||||
check("template <class T> struct A {\n"
|
check("template <class T> struct A {\n"
|
||||||
" A<T>() { x = 0; }\n"
|
" A<T>() { x = 0; }\n"
|
||||||
|
" A<T>(const T & t) { x = t.x; }\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("template <class T> struct A {\n"
|
||||||
|
" A<T>() : x(0) { }\n"
|
||||||
|
" A<T>(const T & t) : x(t.x) { }\n"
|
||||||
|
"private:\n"
|
||||||
|
" int x;\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("template <class T> struct A {\n"
|
||||||
|
" A<T>() : x(0) { }\n"
|
||||||
|
" A<T>(const T & t) : x(t.x) { }\n"
|
||||||
|
"private:\n"
|
||||||
|
" int x;\n"
|
||||||
|
" int y;\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) Member variable 'A::y' is not initialized in the constructor.\n"
|
||||||
|
"[test.cpp:3]: (warning) Member variable 'A::y' is not initialized in the constructor.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_with_this() {
|
void initvar_with_this() {
|
||||||
|
|
Loading…
Reference in New Issue