Permalink
Browse files

Fixed #4695: Infinite recursion inside isRecordTypeWithoutSideEffects()

  • Loading branch information...
zingsheim committed Apr 1, 2013
1 parent 12f5ccf commit 395a474ec28ed01da38797e6c363cc7c33f44f12
Showing with 46 additions and 14 deletions.
  1. +28 −14 lib/checkunusedvar.cpp
  2. +7 −0 lib/checkunusedvar.h
  3. +11 −0 test/testunusedvar.cpp
View
@@ -22,6 +22,7 @@
#include "symboldatabase.h"
#include <algorithm>
#include <cctype>
+#include <utility>
//---------------------------------------------------------------------------
// Register this check class (by creating a static instance of it)
@@ -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()) {
@@ -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;
+}
View
@@ -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;
@@ -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);
@@ -104,6 +109,8 @@ class CPPCHECKLIB CheckUnusedVar : public Check {
"* unassigned variable\n"
"* unused struct member\n";
}
+
+ std::map<const Type *,bool> isRecordTypeWithoutSideEffectsMap;
};
/// @}
//---------------------------------------------------------------------------
View
@@ -153,6 +153,7 @@ class TestUnusedVar : public TestFixture {
TEST_CASE(localvarUnusedGoto); // #4447, #4558 goto
TEST_CASE(crash1);
+ TEST_CASE(crash2);
TEST_CASE(usingNamespace); // #4585
}
@@ -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"

0 comments on commit 395a474

Please sign in to comment.