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

View File

@ -207,8 +207,10 @@ public:
/**
* 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)

View File

@ -275,6 +275,8 @@ private:
TEST_CASE(macroChar);
TEST_CASE(validateCfg);
TEST_CASE(if_sizeof);
}
@ -3608,6 +3610,22 @@ private:
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)