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
|
// find enumerators
|
||||||
for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) {
|
for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) {
|
||||||
if (tok->tokType() != Token::eName)
|
if (tok->tokType() != Token::eName)
|
||||||
|
@ -3256,52 +3311,6 @@ const Token * Scope::addEnum(const Token * tok, bool isCpp)
|
||||||
} else
|
} else
|
||||||
tok2 = nullptr;
|
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;
|
return tok2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2300,8 +2300,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void enum4() { // #7493
|
void enum4() { // #7493
|
||||||
GET_SYMBOL_DB("enum Offsets { O1, O2, O3 };\n"
|
GET_SYMBOL_DB("enum Offsets { O1, O2, O3=5, O4 };\n"
|
||||||
"enum MyEnums { E1=O1+1, E2=O2+1, E3=O3+1 };");
|
"enum MyEnums { E1=O1+1, E2, E3=O3+1 };");
|
||||||
ASSERT(db != nullptr);
|
ASSERT(db != nullptr);
|
||||||
if (!db)
|
if (!db)
|
||||||
return;
|
return;
|
||||||
|
@ -2313,18 +2313,75 @@ private:
|
||||||
// Offsets
|
// Offsets
|
||||||
++scope;
|
++scope;
|
||||||
ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
|
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(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(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(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
|
// MyEnums
|
||||||
++scope;
|
++scope;
|
||||||
ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
|
ASSERT_EQUALS((unsigned int)Scope::eEnum, (unsigned int)scope->type);
|
||||||
ASSERT_EQUALS(3U, scope->enumeratorList.size());
|
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);
|
ASSERT(scope->enumeratorList[0].name->enumerator() == &scope->enumeratorList[0]);
|
||||||
TODO_ASSERT_EQUALS(true, false, scope->enumeratorList[2].value_known);
|
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() {
|
void enum5() {
|
||||||
|
|
Loading…
Reference in New Issue