Skip to content

Commit

Permalink
Refactorized simplification of sizeof without parantheses:
Browse files Browse the repository at this point in the history
- Moved sizeofAddParentheses() behind combineOperators()
- Improved sizeofAddParentheses() to handle all code from unit tests at simplifyTokenList1()
- Removed simplification from simplifyTokenList2()
  • Loading branch information
PKEuS committed Apr 13, 2015
1 parent 4c40664 commit 708a379
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 123 deletions.
116 changes: 14 additions & 102 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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)) {
Expand Down
13 changes: 11 additions & 2 deletions test/testgarbage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class TestGarbage : public TestFixture {
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);
Expand Down Expand Up @@ -242,7 +243,7 @@ class TestGarbage : public TestFixture {
}

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&&...)");
}

Expand Down Expand Up @@ -420,6 +421,14 @@ class TestGarbage : public TestFixture {
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"
Expand Down
19 changes: 0 additions & 19 deletions test/testsimplifytokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ class TestSimplifyTokens : public TestFixture {
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);

Expand Down Expand Up @@ -1416,23 +1414,6 @@ class TestSimplifyTokens : public TestFixture {
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"
Expand Down

0 comments on commit 708a379

Please sign in to comment.