Support sizeof in preprocessor directives

Applied "patch" provided by michaeln123 in #4071
This commit is contained in:
PKEuS 2012-08-22 17:28:06 +02:00
parent 43e01a2b1a
commit f238f3fad5
4 changed files with 33 additions and 3 deletions

View File

@ -1436,6 +1436,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &c
bool modified = true; bool modified = true;
while (modified) { while (modified) {
modified = false; modified = false;
modified |= tokenizer.simplifySizeof();
modified |= tokenizer.simplifyCalculations(); modified |= tokenizer.simplifyCalculations();
modified |= tokenizer.simplifyRedundantParenthesis(); modified |= tokenizer.simplifyRedundantParenthesis();
for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next()) { for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next()) {

View File

@ -3012,7 +3012,7 @@ void Tokenizer::createLinks2()
} }
} }
void Tokenizer::simplifySizeof() bool Tokenizer::simplifySizeof()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "class|struct %var%")) { if (Token::Match(tok, "class|struct %var%")) {
@ -3069,6 +3069,7 @@ void Tokenizer::simplifySizeof()
} }
} }
bool ret = false;
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->str() != "sizeof") if (tok->str() != "sizeof")
continue; continue;
@ -3089,6 +3090,7 @@ void Tokenizer::simplifySizeof()
std::ostringstream sz; std::ostringstream sz;
sz << sizeof 'x'; sz << sizeof 'x';
tok->str(sz.str()); tok->str(sz.str());
ret = true;
continue; continue;
} }
@ -3100,6 +3102,7 @@ void Tokenizer::simplifySizeof()
std::ostringstream sz; std::ostringstream sz;
sz << sizeof 'x'; sz << sizeof 'x';
tok->str(sz.str()); tok->str(sz.str());
ret = true;
continue; continue;
} }
@ -3109,6 +3112,7 @@ void Tokenizer::simplifySizeof()
std::ostringstream ostr; std::ostringstream ostr;
ostr << (Token::getStrLength(tok) + 1); ostr << (Token::getStrLength(tok) + 1);
tok->str(ostr.str()); tok->str(ostr.str());
ret = true;
continue; continue;
} }
@ -3120,6 +3124,7 @@ void Tokenizer::simplifySizeof()
std::ostringstream ostr; std::ostringstream ostr;
ostr << (Token::getStrLength(tok) + 1); ostr << (Token::getStrLength(tok) + 1);
tok->str(ostr.str()); tok->str(ostr.str());
ret = true;
continue; continue;
} }
@ -3192,6 +3197,7 @@ void Tokenizer::simplifySizeof()
if (Token::simpleMatch(tok->next(), "( * )")) { if (Token::simpleMatch(tok->next(), "( * )")) {
tok->str(MathLib::toString<unsigned long>(sizeOfType(tok->tokAt(2)))); tok->str(MathLib::toString<unsigned long>(sizeOfType(tok->tokAt(2))));
tok->deleteNext(3); tok->deleteNext(3);
ret = true;
} }
// sizeof( a ) // sizeof( a )
@ -3201,6 +3207,7 @@ void Tokenizer::simplifySizeof()
tok->deleteThis(); tok->deleteThis();
tok->deleteNext(); tok->deleteNext();
tok->str(sizeOfVar[tok->varId()]); tok->str(sizeOfVar[tok->varId()]);
ret = true;
} else { } else {
// don't try to replace size of variable if variable has // don't try to replace size of variable if variable has
// similar name with type (#329) // similar name with type (#329)
@ -3212,6 +3219,7 @@ void Tokenizer::simplifySizeof()
if (size > 0) { if (size > 0) {
tok->str(MathLib::toString<unsigned int>(size)); tok->str(MathLib::toString<unsigned int>(size));
tok->deleteNext(3); tok->deleteNext(3);
ret = true;
} }
} }
@ -3240,10 +3248,11 @@ void Tokenizer::simplifySizeof()
if (sz > 0) { if (sz > 0) {
tok->str(MathLib::toString<size_t>(sz)); tok->str(MathLib::toString<size_t>(sz));
Token::eraseTokens(tok, tok->next()->link()->next()); Token::eraseTokens(tok, tok->next()->link()->next());
ret = true;
} }
} }
} }
return ret;
} }
bool Tokenizer::simplifyTokenList() bool Tokenizer::simplifyTokenList()

View File

@ -207,8 +207,10 @@ public:
/** /**
* Replace sizeof() to appropriate size. * Replace sizeof() to appropriate size.
* @return true if modifications to token-list are done.
* false if no modifications are done.
*/ */
void simplifySizeof(); bool simplifySizeof();
/** /**
* Simplify variable declarations (split up) * Simplify variable declarations (split up)

View File

@ -275,6 +275,8 @@ private:
TEST_CASE(macroChar); TEST_CASE(macroChar);
TEST_CASE(validateCfg); TEST_CASE(validateCfg);
TEST_CASE(if_sizeof);
} }
@ -3608,6 +3610,22 @@ private:
ASSERT_EQUALS(true, preprocessor.validateCfg("#undef DEBUG", "DEBUG")); ASSERT_EQUALS(true, preprocessor.validateCfg("#undef DEBUG", "DEBUG"));
} }
void if_sizeof() { // #4071
static const char* code = "#if sizeof(wchar_t) == 2\n"
"Fred & Wilma\n"
"#elif sizeof(wchar_t) == 4\n"
"Fred & Wilma\n"
"#else\n"
"#endif";
Settings settings;
Preprocessor preprocessor(&settings, this);
std::istringstream istr(code);
std::map<std::string, std::string> actual;
preprocessor.preprocess(istr, actual, "file.c");
ASSERT_EQUALS("\nFred & Wilma\n\n\n\n\n", actual[""]);
}
}; };
REGISTER_TEST(TestPreprocessor) REGISTER_TEST(TestPreprocessor)