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:
parent
4c40664861
commit
708a379fd2
116
lib/tokenize.cpp
116
lib/tokenize.cpp
|
@ -2974,25 +2974,22 @@ void Tokenizer::createLinks2()
|
||||||
void Tokenizer::sizeofAddParentheses()
|
void Tokenizer::sizeofAddParentheses()
|
||||||
{
|
{
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "sizeof %name%|%num%|%str%")) {
|
Token* next = tok->next();
|
||||||
Token *endToken = tok->next();
|
if (Token::Match(tok, "sizeof !!(") && next && (next->isLiteral() || next->isName() || Token::Match(next, "[*~!]"))) {
|
||||||
while (Token::Match(endToken, "%name%|%num%|%str%|[|(|.|::|++|--|!|~")) {
|
Token *endToken = next;
|
||||||
if (endToken->str() == "[" || endToken->str() == "(")
|
while (Token::Match(endToken->next(), "%name%|%num%|%str%|[|(|.|::|++|--|!|~") || (Token::Match(endToken, "%type% * %op%|?|:|const|;|,"))) {
|
||||||
endToken = endToken->link();
|
if (endToken->strAt(1) == "[" || endToken->strAt(1) == "(")
|
||||||
endToken = endToken->next();
|
endToken = endToken->linkAt(1);
|
||||||
if (Token::simpleMatch(endToken, "- >"))
|
else
|
||||||
endToken = endToken->tokAt(2);
|
endToken = endToken->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endToken) {
|
// Add ( after sizeof and ) behind endToken
|
||||||
// Ok. Add ( after sizeof and ) before endToken
|
tok->insertToken("(");
|
||||||
tok->insertToken("(");
|
endToken->insertToken(")");
|
||||||
endToken->previous()->insertToken(")");
|
Token::createMutualLinks(tok->next(), endToken->next());
|
||||||
Token::createMutualLinks(tok->next(), endToken->previous());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tokenizer::simplifySizeof()
|
bool Tokenizer::simplifySizeof()
|
||||||
|
@ -3059,16 +3056,6 @@ bool Tokenizer::simplifySizeof()
|
||||||
tok->deleteNext(3);
|
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')
|
// sizeof('x')
|
||||||
if (Token::Match(tok, "sizeof ( %char% )")) {
|
if (Token::Match(tok, "sizeof ( %char% )")) {
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
|
@ -3081,16 +3068,6 @@ bool Tokenizer::simplifySizeof()
|
||||||
continue;
|
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")
|
// sizeof ("text")
|
||||||
if (Token::Match(tok->next(), "( %str% )")) {
|
if (Token::Match(tok->next(), "( %str% )")) {
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
|
@ -3103,71 +3080,6 @@ bool Tokenizer::simplifySizeof()
|
||||||
continue;
|
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(*)
|
// sizeof(type *) => sizeof(*)
|
||||||
if (Token::Match(tok->next(), "( %type% * )")) {
|
if (Token::Match(tok->next(), "( %type% * )")) {
|
||||||
tok->next()->deleteNext();
|
tok->next()->deleteNext();
|
||||||
|
@ -3332,11 +3244,11 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
if (!simplifyAddBraces())
|
if (!simplifyAddBraces())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sizeofAddParentheses();
|
|
||||||
|
|
||||||
// Combine tokens..
|
// Combine tokens..
|
||||||
combineOperators();
|
combineOperators();
|
||||||
|
|
||||||
|
sizeofAddParentheses();
|
||||||
|
|
||||||
// Simplify: 0[foo] -> *(foo)
|
// Simplify: 0[foo] -> *(foo)
|
||||||
for (Token* tok = list.front(); tok; tok = tok->next()) {
|
for (Token* tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "0 [") && tok->linkAt(1)) {
|
if (Token::simpleMatch(tok, "0 [") && tok->linkAt(1)) {
|
||||||
|
|
|
@ -72,7 +72,8 @@ private:
|
||||||
TEST_CASE(garbageCode31); // #6539
|
TEST_CASE(garbageCode31); // #6539
|
||||||
TEST_CASE(garbageCode32); // #6135
|
TEST_CASE(garbageCode32); // #6135
|
||||||
TEST_CASE(garbageCode33); // #6613
|
TEST_CASE(garbageCode33); // #6613
|
||||||
TEST_CASE(garbageCode34); // 6626
|
TEST_CASE(garbageCode34); // #6626
|
||||||
|
TEST_CASE(garbageCode35); // #2599, #2604
|
||||||
|
|
||||||
TEST_CASE(garbageValueFlow);
|
TEST_CASE(garbageValueFlow);
|
||||||
TEST_CASE(garbageSymbolDatabase);
|
TEST_CASE(garbageSymbolDatabase);
|
||||||
|
@ -242,7 +243,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void garbageCode7() {
|
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&&...)");
|
checkCode("foo(Args&&...) fn void = { } auto template<typename... bar(Args&&...)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,6 +421,14 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void garbageCode35() {
|
||||||
|
// ticket #2599 segmentation fault
|
||||||
|
checkCode("sizeof");
|
||||||
|
|
||||||
|
// ticket #2604 segmentation fault
|
||||||
|
checkCode("sizeof <= A");
|
||||||
|
}
|
||||||
|
|
||||||
void garbageValueFlow() {
|
void garbageValueFlow() {
|
||||||
// #6089
|
// #6089
|
||||||
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
||||||
|
|
|
@ -79,8 +79,6 @@ private:
|
||||||
TEST_CASE(sizeof19); // #1891 - sizeof 'x'
|
TEST_CASE(sizeof19); // #1891 - sizeof 'x'
|
||||||
TEST_CASE(sizeof20); // #2024 - sizeof a)
|
TEST_CASE(sizeof20); // #2024 - sizeof a)
|
||||||
TEST_CASE(sizeof21); // #2232 - sizeof...(Args)
|
TEST_CASE(sizeof21); // #2232 - sizeof...(Args)
|
||||||
TEST_CASE(sizeof22); // #2599
|
|
||||||
TEST_CASE(sizeof23); // #2604
|
|
||||||
TEST_CASE(sizeofsizeof);
|
TEST_CASE(sizeofsizeof);
|
||||||
TEST_CASE(casting);
|
TEST_CASE(casting);
|
||||||
|
|
||||||
|
@ -1416,23 +1414,6 @@ private:
|
||||||
tok(code);
|
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() {
|
void sizeofsizeof() {
|
||||||
// ticket #1682
|
// ticket #1682
|
||||||
const char code[] = "void f()\n"
|
const char code[] = "void f()\n"
|
||||||
|
|
Loading…
Reference in New Issue