Fix #12151 (Tokenizer::arraySize: enum constant used as index in array initialization) (#5633)

This commit is contained in:
Daniel Marjamäki 2023-11-07 19:19:19 +01:00 committed by GitHub
parent 13e74507dd
commit c1aed9681d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 0 deletions

View File

@ -553,6 +553,10 @@ public:
return mDimensions.at(index_).known;
}
void setDimensions(const std::vector<Dimension> &dimensions_) {
mDimensions = dimensions_;
}
/**
* Checks if the variable is an STL type ('std::')
* E.g.:

View File

@ -3393,6 +3393,8 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration)
} else {
ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults);
}
arraySizeAfterValueFlow();
}
// Warn about unhandled character literals
@ -3807,6 +3809,45 @@ void Tokenizer::arraySize()
}
}
void Tokenizer::arraySizeAfterValueFlow()
{
// After ValueFlow, adjust array sizes.
for (const Variable* var: mSymbolDatabase->variableList()) {
if (!var || !var->isArray())
continue;
if (!Token::Match(var->nameToken(), "%name% [ ] = { ["))
continue;
MathLib::bigint maxIndex = -1;
const Token* const startToken = var->nameToken()->tokAt(4);
const Token* const endToken = startToken->link();
for (const Token* tok = startToken; tok != endToken; tok = tok->next()) {
if (!Token::Match(tok, "[{,] [") || !Token::simpleMatch(tok->linkAt(1), "] ="))
continue;
const Token* expr = tok->next()->astOperand1();
if (expr && expr->hasKnownIntValue())
maxIndex = std::max(maxIndex, expr->getKnownIntValue());
}
if (maxIndex >= 0) {
// insert array size
Token* tok = const_cast<Token*>(var->nameToken()->next());
tok->insertToken(std::to_string(maxIndex + 1));
// ast
tok->astOperand2(tok->next());
// Token::scope
tok->next()->scope(tok->scope());
// Value flow
ValueFlow::Value value(maxIndex + 1);
value.setKnown();
tok->next()->addValue(value);
// Set array dimensions
Dimension d;
d.num = maxIndex + 1;
std::vector<Dimension> dimensions{d};
const_cast<Variable*>(var)->setDimensions(dimensions);
}
}
}
static Token *skipTernaryOp(Token *tok)
{
int colonLevel = 1;

View File

@ -164,6 +164,7 @@ public:
/** Insert array size where it isn't given */
void arraySize();
void arraySizeAfterValueFlow(); // cppcheck-suppress functionConst
/** Simplify labels and 'case|default' syntaxes.
*/

View File

@ -272,6 +272,7 @@ private:
TEST_CASE(cpp14template); // Ticket #6708
TEST_CASE(arraySize);
TEST_CASE(arraySizeAfterValueFlow);
TEST_CASE(labels);
TEST_CASE(simplifyInitVar);
@ -4156,6 +4157,11 @@ private:
ASSERT_EQUALS("; const char c [ 4 ] = \"abc\" ;", tokenizeAndStringify(";const char c[] = { \"abc\" };"));
}
void arraySizeAfterValueFlow() {
const char code[] = "enum {X=10}; int a[] = {[X]=1};";
ASSERT_EQUALS("enum Anonymous0 { X = 10 } ; int a [ 11 ] = { [ X ] = 1 } ;", tokenizeAndStringify(code));
}
void labels() {
ASSERT_EQUALS("void f ( ) { ab : ; a = 0 ; }", tokenizeAndStringify("void f() { ab: a=0; }"));
//ticket #3176