Fixed #4695: Infinite recursion inside isRecordTypeWithoutSideEffects()
This commit is contained in:
parent
12f5ccfb4e
commit
395a474ec2
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 @@ public:
|
|||
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 @@ private:
|
|||
"* unassigned variable\n"
|
||||
"* unused struct member\n";
|
||||
}
|
||||
|
||||
std::map<const Type *,bool> isRecordTypeWithoutSideEffectsMap;
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -153,6 +153,7 @@ private:
|
|||
TEST_CASE(localvarUnusedGoto); // #4447, #4558 goto
|
||||
|
||||
TEST_CASE(crash1);
|
||||
TEST_CASE(crash2);
|
||||
TEST_CASE(usingNamespace); // #4585
|
||||
}
|
||||
|
||||
|
@ -3653,6 +3654,16 @@ private:
|
|||
"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"
|
||||
|
|
Loading…
Reference in New Issue