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())
|
||||
continue;
|
||||
|
||||
// don't check uninstantiated template classes
|
||||
if (scope->classDef->strAt(-1) == ">")
|
||||
continue;
|
||||
|
||||
// There are no constructors.
|
||||
if (scope->numConstructors == 0) {
|
||||
// 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;
|
||||
|
||||
// copy constructor
|
||||
else if ((Token::Match(function.tokenDef, "%var% ( const %var% & )") ||
|
||||
Token::Match(function.tokenDef, "%var% ( const %var% & %var% )")) &&
|
||||
else if ((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.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
|
||||
else if ((Token::Match(function.tokenDef, "%var% ( %var% & )") ||
|
||||
Token::Match(function.tokenDef, "%var% ( %var% & %var% )")) &&
|
||||
else if ((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.type = Function::eCopyConstructor;
|
||||
|
||||
|
@ -929,6 +941,15 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ private:
|
|||
TEST_CASE(virtualDestructorInherited);
|
||||
TEST_CASE(virtualDestructorTemplate);
|
||||
|
||||
TEST_CASE(copyConstructor);
|
||||
TEST_CASE(copyConstructor1);
|
||||
TEST_CASE(copyConstructor2); // ticket #4458
|
||||
|
||||
TEST_CASE(noConstructor1);
|
||||
TEST_CASE(noConstructor2);
|
||||
|
@ -186,7 +187,7 @@ private:
|
|||
checkClass.copyconstructors();
|
||||
}
|
||||
|
||||
void copyConstructor() {
|
||||
void copyConstructor1() {
|
||||
checkCopyConstructor("class F\n"
|
||||
"{\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
|
||||
void checkOpertorEq(const char code[]) {
|
||||
// Clear the error log
|
||||
|
|
|
@ -277,10 +277,29 @@ private:
|
|||
void simple6() { // ticket #4085 - uninstantiated template class
|
||||
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"
|
||||
"};");
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue