Fixed #4458 (False positive: noCopyConstructor in template class)

This commit is contained in:
Robert Reif 2013-01-04 10:35:24 +01:00 committed by Daniel Marjamäki
parent d5dfd5a006
commit d37906041b
4 changed files with 63 additions and 10 deletions

View File

@ -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..

View File

@ -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;
}

View File

@ -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

View File

@ -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() {