5355: False postive var not assigned

Avoid false positive "variable not assigned" for

struct Fred{
};
void foo () {
  Fred fred;
  throw fred;
}

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Heinrich Schuchardt 2014-02-01 22:40:35 +01:00
parent b3bfd5014d
commit 6bfd4af5f7
3 changed files with 58 additions and 1 deletions

View File

@ -1126,7 +1126,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
unreadVariableError(usage._lastAccess, varname); unreadVariableError(usage._lastAccess, varname);
// variable has been read but not written // variable has been read but not written
else if (!usage._write && !usage._allocateMemory && !var->isStlType()) else if (!usage._write && !usage._allocateMemory && !var->isStlType() && !isEmptyType(var->type()))
unassignedVariableError(usage._var->nameToken(), varname); unassignedVariableError(usage._var->nameToken(), varname);
} }
} }
@ -1291,3 +1291,29 @@ bool CheckUnusedVar::isRecordTypeWithoutSideEffects(const Type* type)
withoutSideEffects=false; // unknown types are assumed to have side effects withoutSideEffects=false; // unknown types are assumed to have side effects
return withoutSideEffects; return withoutSideEffects;
} }
bool CheckUnusedVar::isEmptyType(const Type* type)
{
// a type that has no variables and no constructor
std::pair<std::map<const Type *,bool>::iterator,bool> found=isEmptyTypeMap.insert(
std::pair<const Type *,bool>(type,false));
bool & emptyType=found.first->second;
if (!found.second)
return emptyType;
if (type && type->classScope && type->classScope->numConstructors == 0 &&
(type->classScope->varlist.empty())) {
for (std::vector<Type::BaseInfo>::const_iterator i = type->derivedFrom.begin(); i != type->derivedFrom.end(); ++i) {
if (!isEmptyType(i->type)) {
emptyType=false;
return emptyType;
}
}
emptyType=true;
return emptyType;
}
emptyType=false; // unknown types are assumed to be nonempty
return emptyType;
}

View File

@ -75,6 +75,7 @@ public:
private: private:
bool isRecordTypeWithoutSideEffects(const Type* type); bool isRecordTypeWithoutSideEffects(const Type* type);
bool isEmptyType(const Type* type);
// Error messages.. // Error messages..
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname); void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
@ -110,6 +111,9 @@ private:
} }
std::map<const Type *,bool> isRecordTypeWithoutSideEffectsMap; std::map<const Type *,bool> isRecordTypeWithoutSideEffectsMap;
std::map<const Type *,bool> isEmptyTypeMap;
}; };
/// @} /// @}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -34,6 +34,9 @@ public:
private: private:
void run() { void run() {
TEST_CASE(emptyclass); // #5355 - False positive: Variable is not assigned a value.
TEST_CASE(emptystruct); // #5355 - False positive: Variable is not assigned a value.
TEST_CASE(structmember1); TEST_CASE(structmember1);
TEST_CASE(structmember2); TEST_CASE(structmember2);
TEST_CASE(structmember3); TEST_CASE(structmember3);
@ -175,6 +178,30 @@ private:
checkUnusedVar.checkStructMemberUsage(); checkUnusedVar.checkStructMemberUsage();
} }
// #5355 - False positive: Variable is not assigned a value.
void emptyclass() {
functionVariableUsage("class Carla {\n"
"};\n"
"class Fred : Carla {\n"
"};\n"
"void foo() {\n"
" Fred fred;\n"
" throw fred;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
// #5355 - False positive: Variable is not assigned a value.
void emptystruct() {
functionVariableUsage("struct Fred {\n"
"};\n"
"void foo() {\n"
" Fred fred;\n"
" throw fred;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void structmember1() { void structmember1() {
checkStructMemberUsage("struct abc\n" checkStructMemberUsage("struct abc\n"
"{\n" "{\n"