Fixed false negative in unused variable checking when class without side effects inherits from another one.
This commit is contained in:
parent
c7e2490f2b
commit
c537a86363
|
@ -537,16 +537,17 @@ static const Token* doAssignment(Variables &variables, const Token *tok, bool de
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isRecordTypeWithoutSideEffects(const Variable& var)
|
static bool isRecordTypeWithoutSideEffects(const Scope* type)
|
||||||
{
|
{
|
||||||
// a type that has no side effects (no constructors and no members with constructors)
|
// a type that has no side effects (no constructors and no members with constructors)
|
||||||
/** @todo false negative: check base class for side effects */
|
|
||||||
/** @todo false negative: check constructors for side effects */
|
/** @todo false negative: check constructors for side effects */
|
||||||
if (var.type() && var.type()->numConstructors == 0 &&
|
if (type && type->numConstructors == 0 &&
|
||||||
(var.type()->varlist.empty() || var.type()->needInitialization == Scope::True) &&
|
(type->varlist.empty() || type->needInitialization == Scope::True)) {
|
||||||
var.type()->derivedFrom.empty())
|
bool yes = true;
|
||||||
return true;
|
for (std::vector<Scope::BaseInfo>::const_iterator i = type->derivedFrom.begin(); yes && i != type->derivedFrom.end(); ++i)
|
||||||
|
yes = isRecordTypeWithoutSideEffects(i->scope);
|
||||||
|
return yes;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,7 +613,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
type = Variables::pointerPointer;
|
type = Variables::pointerPointer;
|
||||||
else if (i->isPointer())
|
else if (i->isPointer())
|
||||||
type = Variables::pointer;
|
type = Variables::pointer;
|
||||||
else if (_tokenizer->isC() || i->typeEndToken()->isStandardType() || isRecordTypeWithoutSideEffects(*i) || Token::simpleMatch(i->typeStartToken(), "std ::"))
|
else if (_tokenizer->isC() || i->typeEndToken()->isStandardType() || isRecordTypeWithoutSideEffects(i->type()) || Token::simpleMatch(i->typeStartToken(), "std ::"))
|
||||||
type = Variables::standard;
|
type = Variables::standard;
|
||||||
if (type == Variables::none || isPartOfClassStructUnion(i->typeStartToken()))
|
if (type == Variables::none || isPartOfClassStructUnion(i->typeStartToken()))
|
||||||
continue;
|
continue;
|
||||||
|
@ -787,7 +788,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
// is it a user defined type?
|
// is it a user defined type?
|
||||||
if (!type->isStandardType()) {
|
if (!type->isStandardType()) {
|
||||||
const Variable* variable = _tokenizer->getSymbolDatabase()->getVariableFromVarId(start->varId());
|
const Variable* variable = _tokenizer->getSymbolDatabase()->getVariableFromVarId(start->varId());
|
||||||
if (!variable || !isRecordTypeWithoutSideEffects(*variable))
|
if (!variable || !isRecordTypeWithoutSideEffects(variable->type()))
|
||||||
allocate = false;
|
allocate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2580,6 +2580,14 @@ private:
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("class Fred {char c;};\n"
|
||||||
|
"class A : public Fred { int i; };\n"
|
||||||
|
"int foo() {\n"
|
||||||
|
" A a;\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (style) Unused variable: a\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarStruct6() {
|
void localvarStruct6() {
|
||||||
|
|
Loading…
Reference in New Issue