Fixed #7523 (Scope::findEnumerator(): does not find enum constant from other enum type)
This commit is contained in:
parent
d0a1a3123c
commit
f4dd43a71a
|
@ -1206,6 +1206,61 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
}
|
||||
}
|
||||
|
||||
// fill in enumerators in enum
|
||||
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
||||
if (it->type != Scope::eEnum)
|
||||
continue;
|
||||
|
||||
// add enumerators to enumerator tokens
|
||||
for (std::size_t i = 0, end = it->enumeratorList.size(); i < end; ++i)
|
||||
const_cast<Token *>(it->enumeratorList[i].name)->enumerator(&it->enumeratorList[i]);
|
||||
}
|
||||
|
||||
// fill in enumerator values
|
||||
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
||||
if (it->type != Scope::eEnum)
|
||||
continue;
|
||||
|
||||
MathLib::bigint value = 0;
|
||||
|
||||
for (std::size_t i = 0, end = it->enumeratorList.size(); i < end; ++i) {
|
||||
Enumerator & enumerator = it->enumeratorList[i];
|
||||
|
||||
// look for initialization tokens that can be converted to enumerators and convert them
|
||||
if (enumerator.start) {
|
||||
for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) {
|
||||
if (tok3->tokType() == Token::eName) {
|
||||
const Enumerator * e = findEnumerator(tok3);
|
||||
if (e)
|
||||
const_cast<Token *>(tok3)->enumerator(e);
|
||||
}
|
||||
}
|
||||
|
||||
// look for possible constant folding expressions
|
||||
if (enumerator.start) {
|
||||
// rhs of operator:
|
||||
const Token *rhs = enumerator.start->previous()->astOperand2();
|
||||
|
||||
// constant folding of expression:
|
||||
ValueFlow::valueFlowConstantFoldAST(rhs);
|
||||
|
||||
// get constant folded value:
|
||||
if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) {
|
||||
enumerator.value = rhs->values.front().intvalue;
|
||||
enumerator.value_known = true;
|
||||
value = enumerator.value + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not initialized so use default value
|
||||
else {
|
||||
enumerator.value = value++;
|
||||
enumerator.value_known = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find enumerators
|
||||
for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) {
|
||||
if (tok->tokType() != Token::eName)
|
||||
|
@ -3256,52 +3311,6 @@ const Token * Scope::addEnum(const Token * tok, bool isCpp)
|
|||
} else
|
||||
tok2 = nullptr;
|
||||
|
||||
if (tok2) {
|
||||
// add enumerators to enumerator tokens
|
||||
for (std::size_t i = 0, end = enumeratorList.size(); i < end; ++i)
|
||||
const_cast<Token *>(enumeratorList[i].name)->enumerator(&enumeratorList[i]);
|
||||
|
||||
MathLib::bigint value = 0;
|
||||
|
||||
// fill in enumerator values
|
||||
for (std::size_t i = 0, end = enumeratorList.size(); i < end; ++i) {
|
||||
Enumerator & enumerator = enumeratorList[i];
|
||||
|
||||
// look for initialization tokens that can be converted to enumerators and convert them
|
||||
if (enumerator.start) {
|
||||
for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) {
|
||||
if (tok3->tokType() == Token::eName) {
|
||||
const Enumerator * e = findEnumerator(tok3->str());
|
||||
if (e)
|
||||
const_cast<Token *>(tok3)->enumerator(e);
|
||||
}
|
||||
}
|
||||
|
||||
// look for possible constant folding expressions
|
||||
if (enumerator.start) {
|
||||
// rhs of operator:
|
||||
const Token *rhs = enumerator.start->previous()->astOperand2();
|
||||
|
||||
// constant folding of expression:
|
||||
ValueFlow::valueFlowConstantFoldAST(rhs);
|
||||
|
||||
// get constant folded value:
|
||||
if (rhs && rhs->values.size() == 1U && rhs->values.front().isKnown()) {
|
||||
enumerator.value = rhs->values.front().intvalue;
|
||||
enumerator.value_known = true;
|
||||
value = enumerator.value + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not initialized so use default value
|
||||
else {
|
||||
enumerator.value = value++;
|
||||
enumerator.value_known = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tok2;
|
||||
}
|
||||
|
||||
|
|
|
@ -2300,8 +2300,8 @@ private:
|
|||
}
|
||||
|
||||
void enum4() { // #7493
|
||||
GET_SYMBOL_DB("enum Offsets { O1, O2, O3 };\n"
|
||||
"enum MyEnums { E1=O1+1, E2=O2+1, E3=O3+1 };");
|
||||
GET_SYMBOL_DB("enum Offsets { O1, O2, O3=5, O4 };\n"
|
||||
"enum MyEnums { E1=O1+1, E2, E3=O3+1 };");
|
||||
ASSERT(db != nullptr);
|
||||
if (!db)
|
||||
return;
|
||||
|
@ -2313,18 +2313,75 @@ private:
|
|||
// Offsets
|
||||
++scope;
|
||||
ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
|
||||
ASSERT_EQUALS(3U, scope->enumeratorList.size());
|
||||
ASSERT_EQUALS(4U, scope->enumeratorList.size());
|
||||
|
||||
ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[0].name->tokType());
|
||||
ASSERT(scope->enumeratorList[0].scope == &*scope);
|
||||
ASSERT_EQUALS("O1", scope->enumeratorList[0].name->str());
|
||||
ASSERT(scope->enumeratorList[0].start == nullptr);
|
||||
ASSERT(scope->enumeratorList[0].end == nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[0].value_known);
|
||||
ASSERT_EQUALS(0, scope->enumeratorList[0].value);
|
||||
|
||||
ASSERT(scope->enumeratorList[1].name->enumerator() == &scope->enumeratorList[1]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[1].name->tokType());
|
||||
ASSERT(scope->enumeratorList[1].scope == &*scope);
|
||||
ASSERT_EQUALS("O2", scope->enumeratorList[1].name->str());
|
||||
ASSERT(scope->enumeratorList[1].start == nullptr);
|
||||
ASSERT(scope->enumeratorList[1].end == nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[1].value_known);
|
||||
ASSERT_EQUALS(1, scope->enumeratorList[1].value);
|
||||
|
||||
ASSERT(scope->enumeratorList[2].name->enumerator() == &scope->enumeratorList[2]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[2].name->tokType());
|
||||
ASSERT(scope->enumeratorList[2].scope == &*scope);
|
||||
ASSERT_EQUALS("O3", scope->enumeratorList[2].name->str());
|
||||
ASSERT(scope->enumeratorList[2].start != nullptr);
|
||||
ASSERT(scope->enumeratorList[2].end != nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[2].value_known);
|
||||
ASSERT_EQUALS(5, scope->enumeratorList[2].value);
|
||||
|
||||
ASSERT(scope->enumeratorList[3].name->enumerator() == &scope->enumeratorList[3]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[3].name->tokType());
|
||||
ASSERT(scope->enumeratorList[3].scope == &*scope);
|
||||
ASSERT_EQUALS("O4", scope->enumeratorList[3].name->str());
|
||||
ASSERT(scope->enumeratorList[3].start == nullptr);
|
||||
ASSERT(scope->enumeratorList[3].end == nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[3].value_known);
|
||||
ASSERT_EQUALS(6, scope->enumeratorList[3].value);
|
||||
|
||||
// MyEnums
|
||||
++scope;
|
||||
ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
|
||||
ASSERT_EQUALS(3U, scope->enumeratorList.size());
|
||||
TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[0].value_known);
|
||||
TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[1].value_known);
|
||||
TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[2].value_known);
|
||||
|
||||
ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[0].name->tokType());
|
||||
ASSERT(scope->enumeratorList[0].scope == &*scope);
|
||||
ASSERT_EQUALS("E1", scope->enumeratorList[0].name->str());
|
||||
ASSERT(scope->enumeratorList[0].start != nullptr);
|
||||
ASSERT(scope->enumeratorList[0].end != nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[0].value_known);
|
||||
ASSERT_EQUALS(1, scope->enumeratorList[0].value);
|
||||
|
||||
ASSERT(scope->enumeratorList[1].name->enumerator() == &scope->enumeratorList[1]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[1].name->tokType());
|
||||
ASSERT(scope->enumeratorList[1].scope == &*scope);
|
||||
ASSERT_EQUALS("E2", scope->enumeratorList[1].name->str());
|
||||
ASSERT(scope->enumeratorList[1].start == nullptr);
|
||||
ASSERT(scope->enumeratorList[1].end == nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[1].value_known);
|
||||
ASSERT_EQUALS(2, scope->enumeratorList[1].value);
|
||||
|
||||
ASSERT(scope->enumeratorList[2].name->enumerator() == &scope->enumeratorList[2]);
|
||||
ASSERT_EQUALS((unsigned int)Token::eEnumerator, (unsigned int)scope->enumeratorList[2].name->tokType());
|
||||
ASSERT(scope->enumeratorList[2].scope == &*scope);
|
||||
ASSERT_EQUALS("E3", scope->enumeratorList[2].name->str());
|
||||
ASSERT(scope->enumeratorList[2].start != nullptr);
|
||||
ASSERT(scope->enumeratorList[2].end != nullptr);
|
||||
ASSERT_EQUALS(true, scope->enumeratorList[2].value_known);
|
||||
ASSERT_EQUALS(6, scope->enumeratorList[2].value);
|
||||
}
|
||||
|
||||
void enum5() {
|
||||
|
|
Loading…
Reference in New Issue