diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 78708c0c9..e541101f7 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -411,12 +411,18 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (func->type == SymbolDatabase::Func::Constructor) { // check for no arguments: func ( ) - /** @todo check for arguments with default values someday */ if (func->argDef->next() == func->argDef->link()) { hasDefaultConstructor = true; break; } + + /** check for arguments with default values */ + else if (func->argCount() == func->initializedArgCount()) + { + hasDefaultConstructor = true; + break; + } } } @@ -908,6 +914,43 @@ const Token *SymbolDatabase::initBaseInfo(SpaceInfo *info, const Token *tok) return tok2; } + +//--------------------------------------------------------------------------- + +unsigned int SymbolDatabase::Func::argCount() const +{ + unsigned int count = 0; + + if (argDef->link() != argDef->next()) + { + count++; + + for (const Token *tok = argDef->next(); tok && tok->next() && tok->next() != argDef->link(); tok = tok->next()) + { + if (tok->str() == ",") + count++; + } + } + + return count; +} + +unsigned int SymbolDatabase::Func::initializedArgCount() const +{ + unsigned int count = 0; + + if (argDef->link() != argDef->next()) + { + for (const Token *tok = argDef->next(); tok && tok->next() && tok->next() != argDef->link(); tok = tok->next()) + { + if (tok->str() == "=") + count++; + } + } + + return count; +} + //--------------------------------------------------------------------------- SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classDef_, SymbolDatabase::SpaceInfo *nestedIn_) : diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 9cce2a422..0445b35ba 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -117,6 +117,9 @@ public: { } + unsigned int argCount() const; + unsigned int initializedArgCount() const; + 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 diff --git a/test/testclass.cpp b/test/testclass.cpp index 1d5d48f12..f683dc502 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -61,6 +61,7 @@ private: TEST_CASE(uninitVar15); TEST_CASE(uninitVar16); TEST_CASE(uninitVar17); + TEST_CASE(uninitVar18); // ticket #2465 TEST_CASE(uninitVarEnum); TEST_CASE(uninitVarStream); TEST_CASE(uninitVarTypedef); @@ -2026,6 +2027,37 @@ private: ASSERT_EQUALS("[test.cpp:9]: (warning) Member variable 'Bar::foo' is not initialised in the constructor.\n", errout.str()); } + void uninitVar18() // ticket #2465 + { + checkUninitVar("struct Altren\n" + "{\n" + " Altren(int _a = 0) : value(0) { }\n" + " int value;\n" + "};\n" + "class A\n" + "{\n" + "public:\n" + " A() { }\n" + "private:\n" + " Altren value;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + checkUninitVar("struct Altren\n" + "{\n" + " Altren(int _a) : value(0) { }\n" + " int value;\n" + "};\n" + "class A\n" + "{\n" + "public:\n" + " A() { }\n" + "private:\n" + " Altren value;\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:9]: (warning) Member variable 'A::value' is not initialised in the constructor.\n", errout.str()); + } + void uninitVarArray1() { checkUninitVar("class John\n"