Fixed #8111 (performance warning - member variable at constructor)

This commit is contained in:
Daniel Marjamäki 2019-01-07 21:26:58 +01:00
parent 30d53a911e
commit e4525d56a0
2 changed files with 52 additions and 28 deletions

View File

@ -930,37 +930,51 @@ void CheckClass::initializationListUsage()
break;
if (Token::Match(tok, "try|do {"))
break;
if (Token::Match(tok, "%var% =") && tok->strAt(-1) != "*") {
const Variable* var = tok->variable();
if (var && var->scope() == owner && !var->isStatic()) {
if (var->isPointer() || var->isReference() || var->isEnumType() || var->valueType()->type > ValueType::Type::ITERATOR)
continue;
if (!Token::Match(tok, "%var% =") || tok->strAt(-1) == "*")
continue;
bool allowed = true;
for (const Token* tok2 = tok->tokAt(2); tok2 && tok2->str() != ";"; tok2 = tok2->next()) {
const Variable* var2 = tok2->variable();
if (var2) {
if (var2->scope() == owner && tok2->strAt(-1)!=".") { // Is there a dependency between two member variables?
allowed = false;
break;
} else if (var2->isArray() && var2->isLocal()) { // Can't initialize with a local array
allowed = false;
break;
}
} else if (tok2->str() == "this") { // 'this' instance is not completely constructed in initialization list
allowed = false;
break;
} else if (Token::Match(tok2, "%name% (") && tok2->strAt(-1) != "." && isMemberFunc(owner, tok2)) { // Member function called?
allowed = false;
break;
}
const Variable* var = tok->variable();
if (!var || var->scope() != owner || var->isStatic())
continue;
if (var->isPointer() || var->isReference() || var->isEnumType() || var->valueType()->type > ValueType::Type::ITERATOR)
continue;
// Access local var member in rhs => do not warn
bool localmember = false;
visitAstNodes(tok->next()->astOperand2(),
[&](const Token *rhs) {
if (rhs->str() == "." && rhs->astOperand1() && rhs->astOperand1()->variable() && rhs->astOperand1()->variable()->isLocal())
localmember = true;
return ChildrenToVisit::op1_and_op2;
});
if (localmember)
continue;
bool allowed = true;
visitAstNodes(tok->next()->astOperand2(),
[&](const Token *tok2) {
const Variable* var2 = tok2->variable();
if (var2) {
if (var2->scope() == owner && tok2->strAt(-1)!=".") { // Is there a dependency between two member variables?
allowed = false;
return ChildrenToVisit::done;
} else if (var2->isArray() && var2->isLocal()) { // Can't initialize with a local array
allowed = false;
return ChildrenToVisit::done;
}
if (!allowed)
continue;
suggestInitializationList(tok, tok->str());
} else if (tok2->str() == "this") { // 'this' instance is not completely constructed in initialization list
allowed = false;
return ChildrenToVisit::done;
} else if (Token::Match(tok2, "%name% (") && tok2->strAt(-1) != "." && isMemberFunc(owner, tok2)) { // Member function called?
allowed = false;
return ChildrenToVisit::done;
}
}
return ChildrenToVisit::op1_and_op2;
});
if (!allowed)
continue;
suggestInitializationList(tok, tok->str());
}
}
}

View File

@ -6625,6 +6625,16 @@ private:
" Foo(int a, const std::string& b) : Foo(a, bar(b)) {}\n"
"};");
ASSERT_EQUALS("", errout.str());
checkInitializationListUsage("class Fred {\n" // #8111
" std::string a;\n"
" Fred() {\n"
" std::ostringstream ostr;\n"
" ostr << x;\n"
" a = ostr.str();\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
}