Implemented array size calculation for n-dimensional arrays with arbitrary dereferencing (#6657)
This commit is contained in:
parent
33277c6110
commit
1b6e4589da
|
@ -3116,12 +3116,34 @@ bool Tokenizer::simplifySizeof()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "sizeof ( * %name% )") || Token::Match(tok, "sizeof ( %name% [ %num% ] )")) {
|
else if (Token::simpleMatch(tok, "sizeof ( *") || Token::Match(tok, "sizeof ( %name% [")) {
|
||||||
// Some default value..
|
// Some default value..
|
||||||
std::size_t sz = 0;
|
std::size_t sz = 0;
|
||||||
|
|
||||||
const unsigned int varid = tok->tokAt((tok->strAt(2) == "*") ? 3 : 2)->varId();
|
unsigned int derefs = 0;
|
||||||
if ((varid != 0) && (declTokOfVar.find(varid) != declTokOfVar.end())) {
|
|
||||||
|
const Token* nametok = tok->tokAt(2);
|
||||||
|
if (nametok->str() == "*") {
|
||||||
|
do {
|
||||||
|
nametok = nametok->next();
|
||||||
|
derefs++;
|
||||||
|
} while (nametok && nametok->str() == "*");
|
||||||
|
|
||||||
|
if (!Token::Match(nametok, "%name% )"))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
const Token* tok2 = nametok->next();
|
||||||
|
do {
|
||||||
|
tok2 = tok2->link()->next();
|
||||||
|
derefs++;
|
||||||
|
} while (tok2 && tok2->str() == "[");
|
||||||
|
|
||||||
|
if (!tok2 || tok2->str() != ")")
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int varid = nametok->varId();
|
||||||
|
if (derefs != 0 && varid != 0 && declTokOfVar.find(varid) != declTokOfVar.end()) {
|
||||||
// Try to locate variable declaration..
|
// Try to locate variable declaration..
|
||||||
const Token *decltok = declTokOfVar[varid];
|
const Token *decltok = declTokOfVar[varid];
|
||||||
if (Token::Match(decltok->previous(), "%type%|* %name% [")) {
|
if (Token::Match(decltok->previous(), "%type%|* %name% [")) {
|
||||||
|
@ -3131,19 +3153,27 @@ bool Tokenizer::simplifySizeof()
|
||||||
}
|
}
|
||||||
// Multi-dimensional array..
|
// Multi-dimensional array..
|
||||||
if (Token::Match(decltok, "%name% [") && Token::simpleMatch(decltok->linkAt(1), "] [")) {
|
if (Token::Match(decltok, "%name% [") && Token::simpleMatch(decltok->linkAt(1), "] [")) {
|
||||||
const Token *tok2 = decltok->linkAt(1);
|
const Token *tok2 = decltok;
|
||||||
|
for (unsigned int i = 0; i < derefs; i++)
|
||||||
|
tok2 = tok2->linkAt(1); // Skip all dimensions that are derefenced before the sizeof call
|
||||||
while (Token::Match(tok2, "] [ %num% ]")) {
|
while (Token::Match(tok2, "] [ %num% ]")) {
|
||||||
sz = sz * MathLib::toLongNumber(tok2->strAt(2));
|
sz = sz * MathLib::toLongNumber(tok2->strAt(2));
|
||||||
tok2 = tok2->linkAt(3);
|
tok2 = tok2->linkAt(1);
|
||||||
}
|
}
|
||||||
if (Token::simpleMatch(tok2, "] ["))
|
if (Token::simpleMatch(tok2, "] ["))
|
||||||
sz = 0;
|
sz = 0;
|
||||||
}
|
}
|
||||||
} else if (tok->strAt(3) == "[" && tok->tokAt(2)->isStandardType()) {
|
} else if (nametok->strAt(1) == "[" && nametok->isStandardType()) {
|
||||||
sz = sizeOfType(tok->tokAt(2));
|
sz = sizeOfType(nametok);
|
||||||
if (sz == 0)
|
if (sz == 0)
|
||||||
continue;
|
continue;
|
||||||
sz *= static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(4)));
|
const Token *tok2 = nametok->next();
|
||||||
|
while (Token::Match(tok2, "[ %num% ]")) {
|
||||||
|
sz *= static_cast<unsigned long>(MathLib::toLongNumber(tok2->strAt(1)));
|
||||||
|
tok2 = tok2->link()->next();
|
||||||
|
}
|
||||||
|
if (!tok2 || tok2->str() != ")")
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sz > 0) {
|
if (sz > 0) {
|
||||||
|
|
|
@ -894,6 +894,21 @@ private:
|
||||||
"sizeof(i[1]);\n"
|
"sizeof(i[1]);\n"
|
||||||
"sizeof(i);";
|
"sizeof(i);";
|
||||||
ASSERT_EQUALS("char i [ 2 ] [ 20 ] ; 20 ; 40 ;", tok(code));
|
ASSERT_EQUALS("char i [ 2 ] [ 20 ] ; 20 ; 40 ;", tok(code));
|
||||||
|
|
||||||
|
code = "char i[2][20][30];\n"
|
||||||
|
"sizeof(i[1][4][2]);\n"
|
||||||
|
"sizeof(***i);\n"
|
||||||
|
"sizeof(i[1][4]);\n"
|
||||||
|
"sizeof(**i);\n"
|
||||||
|
"sizeof(i[1]);\n"
|
||||||
|
"sizeof(*i);\n"
|
||||||
|
"sizeof(i);";
|
||||||
|
ASSERT_EQUALS("char i [ 2 ] [ 20 ] [ 30 ] ; 1 ; 1 ; 30 ; 30 ; 600 ; 600 ; 1200 ;", tok(code));
|
||||||
|
|
||||||
|
code = "sizeof(char[20]);\n"
|
||||||
|
"sizeof(char[20][3]);\n"
|
||||||
|
"sizeof(char[unknown][3]);";
|
||||||
|
ASSERT_EQUALS("20 ; 60 ; sizeof ( char [ unknown ] [ 3 ] ) ;", tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
void sizeof5() {
|
void sizeof5() {
|
||||||
|
|
Loading…
Reference in New Issue