Implemented support for C++11 uniform initialization in several checks.
This commit is contained in:
parent
f3e0df7501
commit
8130fda4ae
|
@ -447,7 +447,7 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
|
||||||
// Class constructor.. initializing variables like this
|
// Class constructor.. initializing variables like this
|
||||||
// clKalle::clKalle() : var(value) { }
|
// clKalle::clKalle() : var(value) { }
|
||||||
if (initList) {
|
if (initList) {
|
||||||
if (level == 0 && Token::Match(ftok, "%var% (")) {
|
if (level == 0 && Token::Match(ftok, "%var% {|(")) {
|
||||||
if (ftok->str() != func.name()) {
|
if (ftok->str() != func.name()) {
|
||||||
initVar(ftok->str(), scope, usage);
|
initVar(ftok->str(), scope, usage);
|
||||||
} else { // c++11 delegate constructor
|
} else { // c++11 delegate constructor
|
||||||
|
@ -476,42 +476,14 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (level == 0 && Token::Match(ftok, "%var% {") && ftok->str() != "const" && Token::Match(ftok->next()->link()->next(), "%type%|,|{")) {
|
ftok = ftok->next();
|
||||||
if (ftok->str() != func.name()) {
|
level++;
|
||||||
initVar(ftok->str(), scope, usage);
|
|
||||||
} else { // c++11 delegate constructor
|
|
||||||
const Function *member = scope->findFunction(ftok);
|
|
||||||
// member function found
|
|
||||||
if (member) {
|
|
||||||
// recursive call
|
|
||||||
// assume that all variables are initialized
|
|
||||||
if (std::find(callstack.begin(), callstack.end(), member) != callstack.end()) {
|
|
||||||
/** @todo false negative: just bail */
|
|
||||||
assignAllVar(usage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// member function has implementation
|
|
||||||
if (member->hasBody) {
|
|
||||||
// initialize variable use list using member function
|
|
||||||
callstack.push_back(member);
|
|
||||||
initializeVarList(*member, callstack, scope, usage);
|
|
||||||
callstack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// there is a called member function, but it has no implementation, so we assume it initializes everything
|
|
||||||
else {
|
|
||||||
assignAllVar(usage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ftok = ftok->linkAt(1);
|
|
||||||
} else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
|
} else if (level != 0 && Token::Match(ftok, "%var% =")) // assignment in the initializer: var(value = x)
|
||||||
assignVar(ftok->str(), scope, usage);
|
assignVar(ftok->str(), scope, usage);
|
||||||
|
|
||||||
else if (ftok->str() == "(")
|
else if (ftok->str() == "(")
|
||||||
level++;
|
level++;
|
||||||
else if (ftok->str() == ")")
|
else if (ftok->str() == ")" || ftok->str() == "}")
|
||||||
level--;
|
level--;
|
||||||
else if (ftok->str() == "{") {
|
else if (ftok->str() == "{") {
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
|
@ -1993,8 +1965,8 @@ void CheckClass::initializerListOrder()
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
// find all variable initializations in list
|
// find all variable initializations in list
|
||||||
while (tok && tok->str() != "{") {
|
while (tok && tok != func->functionScope->classStart) {
|
||||||
if (Token::Match(tok, "%var% (")) {
|
if (Token::Match(tok, "%var% (|{")) {
|
||||||
const Variable *var = info->getVariable(tok->str());
|
const Variable *var = info->getVariable(tok->str());
|
||||||
|
|
||||||
if (var)
|
if (var)
|
||||||
|
@ -2058,7 +2030,7 @@ void CheckClass::checkSelfInitialization()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (; tok != scope->classStart; tok = tok->next()) {
|
for (; tok != scope->classStart; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "[:,] %var% ( %var% )") && tok->next()->varId() && tok->next()->varId() == tok->tokAt(3)->varId()) {
|
if (Token::Match(tok, "[:,] %var% (|{ %var% )|}") && tok->next()->varId() && tok->next()->varId() == tok->tokAt(3)->varId()) {
|
||||||
selfInitializationError(tok, tok->strAt(1));
|
selfInitializationError(tok, tok->strAt(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
||||||
if (start && Token::simpleMatch(start->previous(), "catch ("))
|
if (start && Token::simpleMatch(start->previous(), "catch ("))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (i->nameToken()->strAt(1) == "(")
|
if (i->nameToken()->strAt(1) == "(" || i->nameToken()->strAt(1) == "{")
|
||||||
continue;
|
continue;
|
||||||
bool stdtype = _tokenizer->isC();
|
bool stdtype = _tokenizer->isC();
|
||||||
const Token* tok = i->typeStartToken();
|
const Token* tok = i->typeStartToken();
|
||||||
|
|
|
@ -5563,6 +5563,14 @@ private:
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::b' is in the wrong place in the initializer list.\n"
|
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::b' is in the wrong place in the initializer list.\n"
|
||||||
"[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::a' is in the wrong place in the initializer list.\n", errout.str());
|
"[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::a' is in the wrong place in the initializer list.\n", errout.str());
|
||||||
|
|
||||||
|
checkInitializerListOrder("class Fred {\n"
|
||||||
|
" int a, b, c;\n"
|
||||||
|
"public:\n"
|
||||||
|
" Fred() : c{0}, b{0}, a{0} { }\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::b' is in the wrong place in the initializer list.\n"
|
||||||
|
"[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::a' is in the wrong place in the initializer list.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkInitializationListUsage(const char code[]) {
|
void checkInitializationListUsage(const char code[]) {
|
||||||
|
@ -5735,6 +5743,13 @@ private:
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Member variable 'i' is initialized by itself.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Member variable 'i' is initialized by itself.\n", errout.str());
|
||||||
|
|
||||||
|
checkSelfInitialization("class Fred {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" Fred() : i{i} {\n"
|
||||||
|
" }\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Member variable 'i' is initialized by itself.\n", errout.str());
|
||||||
|
|
||||||
checkSelfInitialization("class Fred {\n"
|
checkSelfInitialization("class Fred {\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
|
|
|
@ -1461,6 +1461,15 @@ private:
|
||||||
" int mi;\n"
|
" int mi;\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("class Foo : public Bar\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" explicit Foo(int i) : Bar{mi=i} { }\n"
|
||||||
|
"private:\n"
|
||||||
|
" int mi;\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninitVar7() {
|
void uninitVar7() {
|
||||||
|
|
|
@ -615,6 +615,14 @@ private:
|
||||||
" return 1 + iter;\n"
|
" return 1 + iter;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// C++11 style initialization
|
||||||
|
checkUninitVar("int f() {\n"
|
||||||
|
" int i = 0;\n"
|
||||||
|
" int j{ i };\n"
|
||||||
|
" return j;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninitvar3() { // #3844
|
void uninitvar3() { // #3844
|
||||||
|
|
Loading…
Reference in New Issue