Refactorized simplification of sizeof without parantheses:

- Moved sizeofAddParentheses() behind combineOperators()
- Improved sizeofAddParentheses() to handle all code from unit tests at simplifyTokenList1()
- Removed simplification from simplifyTokenList2()
This commit is contained in:
PKEuS 2015-04-13 20:18:07 +02:00
parent 4c40664861
commit 708a379fd2
3 changed files with 25 additions and 123 deletions

View File

@ -2974,25 +2974,22 @@ void Tokenizer::createLinks2()
void Tokenizer::sizeofAddParentheses()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "sizeof %name%|%num%|%str%")) {
Token *endToken = tok->next();
while (Token::Match(endToken, "%name%|%num%|%str%|[|(|.|::|++|--|!|~")) {
if (endToken->str() == "[" || endToken->str() == "(")
endToken = endToken->link();
endToken = endToken->next();
if (Token::simpleMatch(endToken, "- >"))
endToken = endToken->tokAt(2);
Token* next = tok->next();
if (Token::Match(tok, "sizeof !!(") && next && (next->isLiteral() || next->isName() || Token::Match(next, "[*~!]"))) {
Token *endToken = next;
while (Token::Match(endToken->next(), "%name%|%num%|%str%|[|(|.|::|++|--|!|~") || (Token::Match(endToken, "%type% * %op%|?|:|const|;|,"))) {
if (endToken->strAt(1) == "[" || endToken->strAt(1) == "(")
endToken = endToken->linkAt(1);
else
endToken = endToken->next();
}
if (endToken) {
// Ok. Add ( after sizeof and ) before endToken
tok->insertToken("(");
endToken->previous()->insertToken(")");
Token::createMutualLinks(tok->next(), endToken->previous());
}
// Add ( after sizeof and ) behind endToken
tok->insertToken("(");
endToken->insertToken(")");
Token::createMutualLinks(tok->next(), endToken->next());
}
}
}
bool Tokenizer::simplifySizeof()
@ -3059,16 +3056,6 @@ bool Tokenizer::simplifySizeof()
tok->deleteNext(3);
}
// sizeof 'x'
if (tok->next()->type() == Token::eChar) {
tok->deleteThis();
std::ostringstream sz;
sz << sizeof 'x';
tok->str(sz.str());
ret = true;
continue;
}
// sizeof('x')
if (Token::Match(tok, "sizeof ( %char% )")) {
tok->deleteNext();
@ -3081,16 +3068,6 @@ bool Tokenizer::simplifySizeof()
continue;
}
// sizeof "text"
if (tok->next()->type() == Token::eString) {
tok->deleteThis();
std::ostringstream ostr;
ostr << (Token::getStrLength(tok) + 1);
tok->str(ostr.str());
ret = true;
continue;
}
// sizeof ("text")
if (Token::Match(tok->next(), "( %str% )")) {
tok->deleteNext();
@ -3103,71 +3080,6 @@ bool Tokenizer::simplifySizeof()
continue;
}
// sizeof * (...) -> sizeof(*...)
if (Token::simpleMatch(tok->next(), "* (") && !Token::simpleMatch(tok->linkAt(2), ") .")) {
tok->deleteNext();
tok->next()->insertToken("*");
}
// sizeof a++ -> sizeof(a++)
if (Token::Match(tok->next(), "++|-- %name% !!.") || Token::Match(tok->next(), "%name% ++|--")) {
tok->insertToken("(");
tok->tokAt(3)->insertToken(")");
Token::createMutualLinks(tok->next(), tok->tokAt(4));
}
// sizeof 1 => sizeof ( 1 )
if (tok->next()->isNumber()) {
Token *tok2 = tok->next();
tok->insertToken("(");
tok2->insertToken(")");
Token::createMutualLinks(tok->next(), tok2->next());
}
// sizeof int -> sizeof( int )
else if (tok->next()->str() != "(") {
// Add parentheses around the sizeof
int parlevel = 0;
for (Token *tempToken = tok->next(); tempToken; tempToken = tempToken->next()) {
if (tempToken->str() == "(")
++parlevel;
else if (tempToken->str() == ")") {
--parlevel;
if (parlevel == 0 && !Token::Match(tempToken, ") . %name%")) {
// Ok, we should be clean. Add ) after tempToken
tok->insertToken("(");
tempToken->insertToken(")");
Token::createMutualLinks(tok->next(), tempToken->next());
break;
}
}
if (parlevel == 0 && Token::Match(tempToken, "%name%")) {
while (tempToken && tempToken->next() && tempToken->next()->str() == "[") {
tempToken = tempToken->next()->link();
}
if (!tempToken || !tempToken->next()) {
break;
}
if (tempToken->next()->str() == ".") {
// We are checking a class or struct, search next varname
tempToken = tempToken->next();
continue;
} else if (tempToken->next()->type() == Token::eIncDecOp) {
// We have variable++ or variable--, there should be
// nothing after this
tempToken = tempToken->tokAt(2);
}
// Ok, we should be clean. Add ) after tempToken
tok->insertToken("(");
tempToken->insertToken(")");
Token::createMutualLinks(tok->next(), tempToken->next());
break;
}
}
}
// sizeof(type *) => sizeof(*)
if (Token::Match(tok->next(), "( %type% * )")) {
tok->next()->deleteNext();
@ -3332,11 +3244,11 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
if (!simplifyAddBraces())
return false;
sizeofAddParentheses();
// Combine tokens..
combineOperators();
sizeofAddParentheses();
// Simplify: 0[foo] -> *(foo)
for (Token* tok = list.front(); tok; tok = tok->next()) {
if (Token::simpleMatch(tok, "0 [") && tok->linkAt(1)) {

View File

@ -72,7 +72,8 @@ private:
TEST_CASE(garbageCode31); // #6539
TEST_CASE(garbageCode32); // #6135
TEST_CASE(garbageCode33); // #6613
TEST_CASE(garbageCode34); // 6626
TEST_CASE(garbageCode34); // #6626
TEST_CASE(garbageCode35); // #2599, #2604
TEST_CASE(garbageValueFlow);
TEST_CASE(garbageSymbolDatabase);
@ -242,7 +243,7 @@ private:
}
void garbageCode7() {
ASSERT_THROW(checkCode("1 (int j) { return return (c) * sizeof } y[1];"), InternalError);
checkCode("1 (int j) { return return (c) * sizeof } y[1];");
checkCode("foo(Args&&...) fn void = { } auto template<typename... bar(Args&&...)");
}
@ -420,6 +421,14 @@ private:
ASSERT_EQUALS("", errout.str());
}
void garbageCode35() {
// ticket #2599 segmentation fault
checkCode("sizeof");
// ticket #2604 segmentation fault
checkCode("sizeof <= A");
}
void garbageValueFlow() {
// #6089
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"

View File

@ -79,8 +79,6 @@ private:
TEST_CASE(sizeof19); // #1891 - sizeof 'x'
TEST_CASE(sizeof20); // #2024 - sizeof a)
TEST_CASE(sizeof21); // #2232 - sizeof...(Args)
TEST_CASE(sizeof22); // #2599
TEST_CASE(sizeof23); // #2604
TEST_CASE(sizeofsizeof);
TEST_CASE(casting);
@ -1416,23 +1414,6 @@ private:
tok(code);
}
void sizeof22() {
// ticket #2599 segmentation fault
const char code[] = "sizeof\n";
// don't segfault
tok(code);
}
void sizeof23() {
// ticket #2604 segmentation fault
const char code[] = "sizeof <= A\n";
// don't segfault
tok(code);
}
void sizeofsizeof() {
// ticket #1682
const char code[] = "void f()\n"