Ticket #7805: Ignore enumerators when simplifying known variables.
This commit is contained in:
parent
87b08fd405
commit
5119ae84b8
|
@ -41,16 +41,24 @@ namespace {
|
||||||
// in order to store information about the scope
|
// in order to store information about the scope
|
||||||
struct VarIdscopeInfo {
|
struct VarIdscopeInfo {
|
||||||
VarIdscopeInfo()
|
VarIdscopeInfo()
|
||||||
:isExecutable(false), isStructInit(false), startVarid(0) {
|
:isExecutable(false), isStructInit(false), isEnum(false), startVarid(0) {
|
||||||
}
|
}
|
||||||
VarIdscopeInfo(bool _isExecutable, bool _isStructInit, unsigned int _startVarid)
|
VarIdscopeInfo(bool _isExecutable, bool _isStructInit, bool _isEnum, unsigned int _startVarid)
|
||||||
:isExecutable(_isExecutable), isStructInit(_isStructInit), startVarid(_startVarid) {
|
:isExecutable(_isExecutable), isStructInit(_isStructInit), isEnum(_isEnum), startVarid(_startVarid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool isExecutable;
|
const bool isExecutable;
|
||||||
const bool isStructInit;
|
const bool isStructInit;
|
||||||
|
const bool isEnum;
|
||||||
const unsigned int startVarid;
|
const unsigned int startVarid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Return whether tok is the "{" that starts an enumerator list */
|
||||||
|
bool isEnumStart(const Token* tok) {
|
||||||
|
if (!tok || tok->str() != "{")
|
||||||
|
return false;
|
||||||
|
return (tok->strAt(-1) == "enum") || (tok->strAt(-2) == "enum");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith) const
|
const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith) const
|
||||||
|
@ -2428,7 +2436,7 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
||||||
for (const Token *tok = startToken->previous(); tok; tok = tok->previous()) {
|
for (const Token *tok = startToken->previous(); tok; tok = tok->previous()) {
|
||||||
if (!tok->isName() && tok->str() != ":")
|
if (!tok->isName() && tok->str() != ":")
|
||||||
break;
|
break;
|
||||||
if (Token::Match(tok, "class|struct %type% [:{]")) {
|
if (Token::Match(tok, "class|struct|enum %type% [:{]")) {
|
||||||
className = tok->next()->str();
|
className = tok->next()->str();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2437,6 +2445,7 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
||||||
// replace varids..
|
// replace varids..
|
||||||
unsigned int indentlevel = 0;
|
unsigned int indentlevel = 0;
|
||||||
bool initList = false;
|
bool initList = false;
|
||||||
|
bool inEnum = false;
|
||||||
const Token *initListArgLastToken = nullptr;
|
const Token *initListArgLastToken = nullptr;
|
||||||
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
|
for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
|
||||||
if (!tok)
|
if (!tok)
|
||||||
|
@ -2450,11 +2459,14 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
||||||
initListArgLastToken = tok->link();
|
initListArgLastToken = tok->link();
|
||||||
}
|
}
|
||||||
if (tok->str() == "{") {
|
if (tok->str() == "{") {
|
||||||
|
inEnum = isEnumStart(tok);
|
||||||
if (initList && !initListArgLastToken)
|
if (initList && !initListArgLastToken)
|
||||||
initList = false;
|
initList = false;
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
} else if (tok->str() == "}")
|
} else if (tok->str() == "}") {
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
|
inEnum = false;
|
||||||
|
}
|
||||||
else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
|
else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
|
||||||
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
||||||
if (it != variableId.end()) {
|
if (it != variableId.end()) {
|
||||||
|
@ -2473,10 +2485,12 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
if (!inEnum) {
|
||||||
if (it != variableId.end()) {
|
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
||||||
tok->varId(it->second);
|
if (it != variableId.end()) {
|
||||||
setVarIdStructMembers(&tok, structMembers, &_varId);
|
tok->varId(it->second);
|
||||||
|
setVarIdStructMembers(&tok, structMembers, &_varId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (indentlevel == 0 && tok->str() == ":" && !initListArgLastToken)
|
} else if (indentlevel == 0 && tok->str() == ":" && !initListArgLastToken)
|
||||||
|
@ -2565,7 +2579,7 @@ void Tokenizer::setVarIdPass1()
|
||||||
variableId.swap(scopeInfo.top());
|
variableId.swap(scopeInfo.top());
|
||||||
scopeInfo.pop();
|
scopeInfo.pop();
|
||||||
} else if (tok->str() == "{")
|
} else if (tok->str() == "{")
|
||||||
scopeStack.push(VarIdscopeInfo(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", _varId));
|
scopeStack.push(VarIdscopeInfo(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/false, _varId));
|
||||||
} else if (!initlist && tok->str()=="(") {
|
} else if (!initlist && tok->str()=="(") {
|
||||||
const Token * newFunctionDeclEnd = nullptr;
|
const Token * newFunctionDeclEnd = nullptr;
|
||||||
if (!scopeStack.top().isExecutable)
|
if (!scopeStack.top().isExecutable)
|
||||||
|
@ -2599,7 +2613,7 @@ void Tokenizer::setVarIdPass1()
|
||||||
scopeInfo.push(variableId);
|
scopeInfo.push(variableId);
|
||||||
}
|
}
|
||||||
initlist = false;
|
initlist = false;
|
||||||
scopeStack.push(VarIdscopeInfo(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", _varId));
|
scopeStack.push(VarIdscopeInfo(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", isEnumStart(tok), _varId));
|
||||||
} else { /* if (tok->str() == "}") */
|
} else { /* if (tok->str() == "}") */
|
||||||
bool isNamespace = false;
|
bool isNamespace = false;
|
||||||
for (const Token *tok1 = tok->link()->previous(); tok1 && tok1->isName(); tok1 = tok1->previous())
|
for (const Token *tok1 = tok->link()->previous(); tok1 && tok1->isName(); tok1 = tok1->previous())
|
||||||
|
@ -2778,10 +2792,12 @@ void Tokenizer::setVarIdPass1()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
if (!scopeStack.top().isEnum) {
|
||||||
if (it != variableId.end()) {
|
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
|
||||||
tok->varId(it->second);
|
if (it != variableId.end()) {
|
||||||
setVarIdStructMembers(&tok, structMembers, &_varId);
|
tok->varId(it->second);
|
||||||
|
setVarIdStructMembers(&tok, structMembers, &_varId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok, "::|. %name%")) {
|
} else if (Token::Match(tok, "::|. %name%")) {
|
||||||
// Don't set varid after a :: or . token
|
// Don't set varid after a :: or . token
|
||||||
|
|
|
@ -179,6 +179,7 @@ private:
|
||||||
TEST_CASE(simplifyKnownVariables58); // ticket #5268
|
TEST_CASE(simplifyKnownVariables58); // ticket #5268
|
||||||
TEST_CASE(simplifyKnownVariables59); // skip for header
|
TEST_CASE(simplifyKnownVariables59); // skip for header
|
||||||
TEST_CASE(simplifyKnownVariables60); // #6829
|
TEST_CASE(simplifyKnownVariables60); // #6829
|
||||||
|
TEST_CASE(simplifyKnownVariables61); // #7805
|
||||||
TEST_CASE(simplifyKnownVariablesBailOutAssign1);
|
TEST_CASE(simplifyKnownVariablesBailOutAssign1);
|
||||||
TEST_CASE(simplifyKnownVariablesBailOutAssign2);
|
TEST_CASE(simplifyKnownVariablesBailOutAssign2);
|
||||||
TEST_CASE(simplifyKnownVariablesBailOutAssign3); // #4395 - nested assignments
|
TEST_CASE(simplifyKnownVariablesBailOutAssign3); // #4395 - nested assignments
|
||||||
|
@ -533,7 +534,6 @@ private:
|
||||||
return tokenizer.tokens()->stringifyList(true,true,true,true,false);
|
return tokenizer.tokens()->stringifyList(true,true,true,true,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tokenize1() {
|
void tokenize1() {
|
||||||
const char code[] = "void f ( )\n"
|
const char code[] = "void f ( )\n"
|
||||||
"{ if ( p . y ( ) > yof ) { } }";
|
"{ if ( p . y ( ) > yof ) { } }";
|
||||||
|
@ -2653,6 +2653,19 @@ private:
|
||||||
"}", tokenizeAndStringify(code, true));
|
"}", tokenizeAndStringify(code, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyKnownVariables61() { // #7805
|
||||||
|
tokenizeAndStringify("static const int XX = 0;\n"
|
||||||
|
"enum E { XX };\n"
|
||||||
|
"struct s {\n"
|
||||||
|
" enum Bar {\n"
|
||||||
|
" XX,\n"
|
||||||
|
" Other\n"
|
||||||
|
" };\n"
|
||||||
|
" enum { XX };\n"
|
||||||
|
"};", /*simplify=*/true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyKnownVariablesBailOutAssign1() {
|
void simplifyKnownVariablesBailOutAssign1() {
|
||||||
const char code[] = "int foo() {\n"
|
const char code[] = "int foo() {\n"
|
||||||
" int i; i = 0;\n"
|
" int i; i = 0;\n"
|
||||||
|
|
Loading…
Reference in New Issue