diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index f43cceb60..9f2bbb1e5 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -537,16 +537,17 @@ static const Token* doAssignment(Variables &variables, const Token *tok, bool de 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) - /** @todo false negative: check base class for side effects */ /** @todo false negative: check constructors for side effects */ - if (var.type() && var.type()->numConstructors == 0 && - (var.type()->varlist.empty() || var.type()->needInitialization == Scope::True) && - var.type()->derivedFrom.empty()) - return true; - + if (type && type->numConstructors == 0 && + (type->varlist.empty() || type->needInitialization == Scope::True)) { + bool yes = true; + for (std::vector::const_iterator i = type->derivedFrom.begin(); yes && i != type->derivedFrom.end(); ++i) + yes = isRecordTypeWithoutSideEffects(i->scope); + return yes; + } return false; } @@ -612,7 +613,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const type = Variables::pointerPointer; else if (i->isPointer()) 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; if (type == Variables::none || isPartOfClassStructUnion(i->typeStartToken())) continue; @@ -787,7 +788,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const // is it a user defined type? if (!type->isStandardType()) { const Variable* variable = _tokenizer->getSymbolDatabase()->getVariableFromVarId(start->varId()); - if (!variable || !isRecordTypeWithoutSideEffects(*variable)) + if (!variable || !isRecordTypeWithoutSideEffects(variable->type())) allocate = false; } } diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index a28765767..fb30bf008 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -2580,6 +2580,14 @@ private: " return 0;\n" "}\n"); 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() {