Implemented array size calculation for n-dimensional arrays with arbitrary dereferencing (#6657)

This commit is contained in:
PKEuS 2015-05-11 17:30:11 +02:00
parent 33277c6110
commit 1b6e4589da
2 changed files with 54 additions and 9 deletions

View File

@ -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) {

View File

@ -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() {