Skip to content

Commit

Permalink
Fixed #4695: Infinite recursion inside isRecordTypeWithoutSideEffects()
Browse files Browse the repository at this point in the history
  • Loading branch information
zingsheim committed Apr 1, 2013
1 parent 12f5ccf commit 395a474
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 14 deletions.
42 changes: 28 additions & 14 deletions lib/checkunusedvar.cpp
Expand Up @@ -22,6 +22,7 @@
#include "symboldatabase.h"
#include <algorithm>
#include <cctype>
#include <utility>
//---------------------------------------------------------------------------

// Register this check class (by creating a static instance of it)
Expand Down Expand Up @@ -618,20 +619,6 @@ static const Token* doAssignment(Variables &variables, const Token *tok, bool de
return tok;
}

static bool isRecordTypeWithoutSideEffects(const Type* type)
{
// a type that has no side effects (no constructors and no members with constructors)
/** @todo false negative: check constructors for side effects */
if (type && type->classScope && type->classScope->numConstructors == 0 &&
(type->classScope->varlist.empty() || type->needInitialization == Type::True)) {
bool yes = true;
for (std::vector<Type::BaseInfo>::const_iterator i = type->derivedFrom.begin(); yes && i != type->derivedFrom.end(); ++i)
yes = isRecordTypeWithoutSideEffects(i->type);
return yes;
}
return false;
}

static bool isPartOfClassStructUnion(const Token* tok)
{
for (; tok; tok = tok->previous()) {
Expand Down Expand Up @@ -1254,3 +1241,30 @@ void CheckUnusedVar::unusedStructMemberError(const Token *tok, const std::string
{
reportError(tok, Severity::style, "unusedStructMember", "struct or union member '" + structname + "::" + varname + "' is never used.");
}

bool CheckUnusedVar::isRecordTypeWithoutSideEffects(const Type* type)
{
// a type that has no side effects (no constructors and no members with constructors)
/** @todo false negative: check constructors for side effects */

std::pair<std::map<Type const *,bool>::iterator,bool> found=isRecordTypeWithoutSideEffectsMap.insert(
std::pair<const Type *,bool>(type,false)); //Initialize with side effects for possilbe recursions
bool & withoutSideEffects=found.first->second;
if (!found.second)
return withoutSideEffects;

if (type && type->classScope && type->classScope->numConstructors == 0 &&
(type->classScope->varlist.empty() || type->needInitialization == Type::True)) {
for (std::vector<Type::BaseInfo>::const_iterator i = type->derivedFrom.begin(); i != type->derivedFrom.end(); ++i) {
if (!isRecordTypeWithoutSideEffects(i->type)) {
withoutSideEffects=false;
return withoutSideEffects;
}
}
withoutSideEffects=true;
return withoutSideEffects;
}

withoutSideEffects=false; // unknown types are assumed to have side effects
return withoutSideEffects;
}
7 changes: 7 additions & 0 deletions lib/checkunusedvar.h
Expand Up @@ -22,10 +22,13 @@
#define CheckUnusedVarH
//---------------------------------------------------------------------------

#include <map>

#include "config.h"
#include "check.h"
#include "settings.h"

class Type;
class Token;
class Scope;
class Variables;
Expand Down Expand Up @@ -72,6 +75,8 @@ class CPPCHECKLIB CheckUnusedVar : public Check {
void checkStructMemberUsage();

private:
bool isRecordTypeWithoutSideEffects(const Type* type);

// Error messages..
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
void unusedVariableError(const Token *tok, const std::string &varname);
Expand Down Expand Up @@ -104,6 +109,8 @@ class CPPCHECKLIB CheckUnusedVar : public Check {
"* unassigned variable\n"
"* unused struct member\n";
}

std::map<const Type *,bool> isRecordTypeWithoutSideEffectsMap;
};
/// @}
//---------------------------------------------------------------------------
Expand Down
11 changes: 11 additions & 0 deletions test/testunusedvar.cpp
Expand Up @@ -153,6 +153,7 @@ class TestUnusedVar : public TestFixture {
TEST_CASE(localvarUnusedGoto); // #4447, #4558 goto

TEST_CASE(crash1);
TEST_CASE(crash2);
TEST_CASE(usingNamespace); // #4585
}

Expand Down Expand Up @@ -3653,6 +3654,16 @@ class TestUnusedVar : public TestFixture {
"SAL_WNODEPRECATED_DECLARATIONS_POP"); // #4033
}

void crash2() {
functionVariableUsage("template<unsigned dim>\n"
"struct Y: Y<dim-1> { };\n"
"template<>\n"
"struct Y<0> {};\n"
"void f() {\n"
" Y y;\n"
"}"); // #4695
}

void usingNamespace() {
functionVariableUsage("int foo() {\n"
" using namespace ::com::sun::star::i18n;\n"
Expand Down

0 comments on commit 395a474

Please sign in to comment.