Rewritten handling of declaration specifiers:

- Removed simplifyConst() because it did the opposite of the (superior) simplifyStaticConst()
- Execute simplifyStaticConst() in simplifyTokenList1() - there is no reason to defer it, and it is required to properly parse declarations like "unsigned static int i;"
- Fixed simplifyStaticConst() to handle more patterns. It did not work at the beginning of the token list and for function arguments
- Reimplemented Tokenizer::simplifyStdType()
-> properly support all possible ways to declare integers as requested by the standard, instead of only a few common permutations of "unsigned|signed", "short|char|long|int"
-> Fixed parsing of _Complex/complex types
This commit is contained in:
PKEuS 2015-08-27 14:34:00 +02:00
parent eb3b3de81f
commit 2ace3d3144
5 changed files with 114 additions and 133 deletions

View File

@ -1008,6 +1008,8 @@ void Token::stringify(std::ostream& os, bool varid, bool attributes, bool macro)
os << "unsigned "; os << "unsigned ";
else if (isSigned()) else if (isSigned())
os << "signed "; os << "signed ";
if (isComplex())
os << "_Complex ";
if (isLong()) { if (isLong()) {
if (_tokType == eString || _tokType == eChar) if (_tokType == eString || _tokType == eChar)
os << "L"; os << "L";

View File

@ -1754,20 +1754,24 @@ bool Tokenizer::tokenizeCondition(const std::string &code)
// Remove "volatile", "inline", "register", and "restrict" // Remove "volatile", "inline", "register", and "restrict"
simplifyKeyword(); simplifyKeyword();
// Concatenate double sharp: 'a ## b' -> 'ab'
concatenateDoubleSharp();
// Link brackets (, [ and {
createLinks();
// Order keywords "static" and "const"
simplifyStaticConst();
// convert platform dependent types to standard types // convert platform dependent types to standard types
// 32 bits: size_t -> unsigned long // 32 bits: size_t -> unsigned long
// 64 bits: size_t -> unsigned long long // 64 bits: size_t -> unsigned long long
simplifyPlatformTypes(); simplifyPlatformTypes();
// collapse compound standard types into a single token // collapse compound standard types into a single token
// unsigned long long int => long _isUnsigned=true,_isLong=true // unsigned long long int => long (with _isUnsigned=true,_isLong=true)
simplifyStdType(); simplifyStdType();
// Concatenate double sharp: 'a ## b' -> 'ab'
concatenateDoubleSharp();
createLinks();
// replace 'NULL' and similar '0'-defined macros with '0' // replace 'NULL' and similar '0'-defined macros with '0'
simplifyNull(); simplifyNull();
@ -3422,13 +3426,16 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// Put ^{} statements in asm() // Put ^{} statements in asm()
simplifyAsm2(); simplifyAsm2();
// Order keywords "static" and "const"
simplifyStaticConst();
// convert platform dependent types to standard types // convert platform dependent types to standard types
// 32 bits: size_t -> unsigned long // 32 bits: size_t -> unsigned long
// 64 bits: size_t -> unsigned long long // 64 bits: size_t -> unsigned long long
simplifyPlatformTypes(); simplifyPlatformTypes();
// collapse compound standard types into a single token // collapse compound standard types into a single token
// unsigned long long int => long _isUnsigned=true,_isLong=true // unsigned long long int => long (with _isUnsigned=true,_isLong=true)
simplifyStdType(); simplifyStdType();
if (_settings->terminated()) if (_settings->terminated())
@ -3440,8 +3447,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
if (_settings->terminated()) if (_settings->terminated())
return false; return false;
simplifyConst();
// struct simplification "struct S {} s; => struct S { } ; S s ; // struct simplification "struct S {} s; => struct S { } ; S s ;
simplifyStructDecl(); simplifyStructDecl();
@ -3665,8 +3670,6 @@ bool Tokenizer::simplifyTokenList2()
simplifyEmptyNamespaces(); simplifyEmptyNamespaces();
simplifyStaticConst();
simplifyMathFunctions(); simplifyMathFunctions();
validate(); validate();
@ -5644,88 +5647,59 @@ void Tokenizer::simplifyPlatformTypes()
void Tokenizer::simplifyStdType() void Tokenizer::simplifyStdType()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
// long unsigned => unsigned long if (Token::Match(tok, "char|short|int|long|unsigned|signed|double|float") || (_settings->standards.c >= Standards::C99 && Token::Match(tok, "complex|_Complex"))) {
if (Token::Match(tok, "char|short|int|long unsigned|signed")) { bool isFloat= false;
const bool isUnsigned = tok->next()->str() == "unsigned"; bool isSigned = false;
tok->deleteNext(); bool isUnsigned = false;
tok->isUnsigned(isUnsigned); bool isComplex = false;
tok->isSigned(!isUnsigned); unsigned int countLong = 0;
} Token* typeSpec = nullptr;
else if (Token::Match(tok, "float|double complex|_Complex")) { Token* tok2 = tok;
tok->deleteNext(); for (; tok2->next(); tok2 = tok2->next()) {
tok->isComplex(true); if (tok2->str() == "long") {
} countLong++;
if (!isFloat)
else if (!Token::Match(tok, "unsigned|signed|char|short|int|long")) typeSpec = tok2;
continue; } else if (tok2->str() == "short") {
typeSpec = tok2;
// check if signed or unsigned specified } else if (tok2->str() == "unsigned")
if (Token::Match(tok, "unsigned|signed")) { isUnsigned = true;
const bool isUnsigned = tok->str() == "unsigned"; else if (tok2->str() == "signed")
isSigned = true;
// unsigned i => unsigned int i else if (Token::Match(tok2, "float|double")) {
if (!Token::Match(tok->next(), "char|short|int|long")) isFloat = true;
tok->str("int"); typeSpec = tok2;
else } else if (_settings->standards.c >= Standards::C99 && Token::Match(tok2, "complex|_Complex"))
tok->deleteThis(); isComplex = !isFloat || tok2->str() == "_Complex" || Token::Match(tok2->next(), "*|&|%name%"); // Ensure that "complex" is not the variables name
tok->isUnsigned(isUnsigned); else if (Token::Match(tok2, "char|int")) {
tok->isSigned(!isUnsigned); if (!typeSpec)
} typeSpec = tok2;
} else
if (tok->str() == "int") { break;
if (tok->strAt(1) == "long") {
tok->str("long");
tok->deleteNext();
} else if (tok->strAt(1) == "short") {
tok->str("short");
tok->deleteNext();
} }
if (tok->strAt(1) == "long") {
tok->isLong(true); if (!typeSpec) { // unsigned i; or similar declaration
tok->deleteNext(); if (!isComplex) { // Ensure that "complex" is not the variables name
} tok->str("int");
if (Token::Match(tok->next(), "unsigned|signed")) { tok->isSigned(isSigned);
tok->isUnsigned(tok->next()->str() == "unsigned"); tok->isUnsigned(isUnsigned);
tok->isSigned(tok->next()->str() == "signed"); }
tok->deleteNext(); } else {
if (tok->strAt(1) == "long") typeSpec->isLong(typeSpec->isLong() || (isFloat && countLong == 1) || countLong > 1);
tok->deleteNext(); typeSpec->isComplex(typeSpec->isComplex() || (isFloat && isComplex));
else if (tok->strAt(1) == "short") typeSpec->isSigned(typeSpec->isSigned() || isSigned);
tok->deleteNext(); typeSpec->isUnsigned(typeSpec->isUnsigned() || isUnsigned);
}
} else if (tok->str() == "long") { // Remove specifiers
if (tok->strAt(1) == "long") { const Token* tok3 = tok->previous();
tok->isLong(true); tok2 = tok2->previous();
tok->deleteNext(); while (tok3 != tok2) {
} if (tok2 != typeSpec &&
if (tok->strAt(1) == "int") { (isComplex || !Token::Match(tok2, "complex|_Complex"))) // Ensure that "complex" is not the variables name
tok->deleteNext(); tok2->deleteThis();
if (Token::Match(tok->next(), "unsigned|signed")) { tok2 = tok2->previous();
tok->isUnsigned(tok->next()->str() == "unsigned");
tok->isSigned(tok->next()->str() == "signed");
tok->deleteNext();
} }
} else if (tok->strAt(1) == "double") {
tok->str("double");
tok->isLong(true);
tok->deleteNext();
} else if (Token::Match(tok->next(), "unsigned|signed")) {
tok->isUnsigned(tok->next()->str() == "unsigned");
tok->isSigned(tok->next()->str() == "signed");
tok->deleteNext();
if (tok->strAt(1) == "int")
tok->deleteNext();
}
} else if (tok->str() == "short") {
if (tok->strAt(1) == "int")
tok->deleteNext();
if (Token::Match(tok->next(), "unsigned|signed")) {
tok->isUnsigned(tok->next()->str() == "unsigned");
tok->isSigned(tok->next()->str() == "signed");
tok->deleteNext();
if (tok->strAt(1) == "int")
tok->deleteNext();
} }
} }
} }
@ -5751,20 +5725,22 @@ void Tokenizer::simplifyStaticConst()
Token* leftTok = tok; Token* leftTok = tok;
for (; leftTok; leftTok = leftTok->previous()) { for (; leftTok; leftTok = leftTok->previous()) {
if (!Token::Match(leftTok, "%type%|static|const|extern") || if (!Token::Match(leftTok, "%type%|static|const|extern") ||
(isCPP() && Token::Match(leftTok, "private:|protected:|public:"))) (isCPP() && Token::Match(leftTok, "private:|protected:|public:|operator")))
break; break;
} }
// The token preceding the declaration should indicate the start of a statement // The token preceding the declaration should indicate the start of a declaration
if (!leftTok || if (leftTok == tok ||
leftTok == tok || (leftTok && !Token::Match(leftTok, ";|{|}|(|,|private:|protected:|public:"))) {
!Token::Match(leftTok, ";|{|}|private:|protected:|public:")) {
continue; continue;
} }
// Move the qualifier to the left-most position in the declaration // Move the qualifier to the left-most position in the declaration
tok->deleteNext(); tok->deleteNext();
if (leftTok->next()) if (!leftTok) {
list.front()->insertToken(qualifier, false);
list.front()->swapWithNext();
} else if (leftTok->next())
leftTok->next()->insertToken(qualifier, true); leftTok->next()->insertToken(qualifier, true);
else else
leftTok->insertToken(qualifier); leftTok->insertToken(qualifier);
@ -8645,23 +8621,6 @@ std::string Tokenizer::simplifyString(const std::string &source)
return str; return str;
} }
void Tokenizer::simplifyConst()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->isStandardType() && tok->strAt(1) == "const") {
tok->swapWithNext();
} else if (Token::Match(tok, "struct %type% const")) {
tok->next()->swapWithNext();
tok->swapWithNext();
} else if (Token::Match(tok, "%type% const") &&
(!tok->previous() || Token::Match(tok->previous(), "[;{}(,]")) &&
tok->str().find(':') == std::string::npos &&
tok->str() != "operator") {
tok->swapWithNext();
}
}
}
void Tokenizer::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) void Tokenizer::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{ {
Tokenizer t(settings, errorLogger); Tokenizer t(settings, errorLogger);

View File

@ -527,11 +527,6 @@ private:
*/ */
const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const; const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const;
/**
* Change "int const x;" into "const int x;"
*/
void simplifyConst();
/** /**
* simplify "while (0)" * simplify "while (0)"
*/ */

View File

@ -684,7 +684,7 @@ private:
"class Fred { " "class Fred { "
"" ""
"const unsigned int * * get ( ) { return test ; } " "const unsigned int * * get ( ) { return test ; } "
"const static unsigned int * test ( const unsigned int * p ) { return p ; } " "static const unsigned int * test ( const unsigned int * p ) { return p ; } "
"} ;"; "} ;";
ASSERT_EQUALS(expected, tok(code, false)); ASSERT_EQUALS(expected, tok(code, false));

View File

@ -3324,7 +3324,7 @@ private:
static char exp[] = "struct S { " static char exp[] = "struct S { "
"char * a ; " "char * a ; "
"char & b ; " "char & b ; "
"const static char * c ; " "static const char * c ; "
"} ;"; "} ;";
ASSERT_EQUALS(exp, tokenizeAndStringify(code)); ASSERT_EQUALS(exp, tokenizeAndStringify(code));
} }
@ -3464,7 +3464,7 @@ private:
"a = SZ;\n" "a = SZ;\n"
"}\n"; "}\n";
const char expected[] = const char expected[] =
"const static char str [ 5 ] = \"abcd\" ;\n\nvoid f ( ) {\na = 5 ;\n}"; "static const char str [ 5 ] = \"abcd\" ;\n\nvoid f ( ) {\na = 5 ;\n}";
ASSERT_EQUALS(expected, tokenizeAndStringify(code,true)); ASSERT_EQUALS(expected, tokenizeAndStringify(code,true));
} }
@ -3746,11 +3746,11 @@ private:
" unsigned int *foo = &x;" " unsigned int *foo = &x;"
"}"; "}";
ASSERT_EQUALS("unsigned int x ; " ASSERT_EQUALS("unsigned int x ; "
"const static unsigned int A = 1 ; " "static const unsigned int A = 1 ; "
"const static unsigned int B = A ; " "static const unsigned int B = A ; "
"const static unsigned int C = 0 ; " "static const unsigned int C = 0 ; "
"const static unsigned int D = A ; " "static const unsigned int D = A ; "
"const static unsigned int E = 0 ; " "static const unsigned int E = 0 ; "
"void f ( ) { " "void f ( ) { "
"unsigned int * foo ; " "unsigned int * foo ; "
"foo = & x ; " "foo = & x ; "
@ -4590,9 +4590,34 @@ private:
const char expected[] = "signed short x ;"; const char expected[] = "signed short x ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code)); ASSERT_EQUALS(expected, tokenizeAndStringify(code));
} }
{
const char code[] = "unsigned static short const int i;";
const char expected[] = "static const unsigned short i ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
}
{ {
const char code[] = "float complex x;"; const char code[] = "float complex x;";
const char expected[] = "float x ;"; const char expected[] = "_Complex float x ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
}
{
const char code[] = "complex float x;";
const char expected[] = "_Complex float x ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
}
{
const char code[] = "complex long double x;";
const char expected[] = "_Complex long double x ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
}
{
const char code[] = "long double complex x;";
const char expected[] = "_Complex long double x ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
}
{
const char code[] = "double complex;";
const char expected[] = "double complex ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code)); ASSERT_EQUALS(expected, tokenizeAndStringify(code));
} }
} }
@ -8288,12 +8313,12 @@ private:
"static const signed long long i4 ;\n" "static const signed long long i4 ;\n"
"static const signed long long i5 ;\n" "static const signed long long i5 ;\n"
"static const signed long long i6 ;\n" "static const signed long long i6 ;\n"
"static const long long signed int i7 ;\n" "static const signed long long i7 ;\n"
"static const long long signed int i8 ;\n" "static const signed long long i8 ;\n"
"static const signed int long long i9 ;\n" "static const signed long long i9 ;\n"
"static const signed int long long i10 ;\n" "static const signed long long i10 ;\n"
"static const int signed long long i11 ;\n" "static const signed long long i11 ;\n"
"static const int signed long long i12 ;\n" "static const signed long long i12 ;\n"
"static const signed long long i13 ;\n" "static const signed long long i13 ;\n"
"static const signed long long i14 ;\n" "static const signed long long i14 ;\n"
"static const signed long long i15 ;\n" "static const signed long long i15 ;\n"