From f238f3fad5e5068585b3f36eae2a540540cc5b5f Mon Sep 17 00:00:00 2001 From: PKEuS Date: Wed, 22 Aug 2012 17:28:06 +0200 Subject: [PATCH] Support sizeof in preprocessor directives Applied "patch" provided by michaeln123 in #4071 --- lib/preprocessor.cpp | 1 + lib/tokenize.cpp | 13 +++++++++++-- lib/tokenize.h | 4 +++- test/testpreprocessor.cpp | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 47a64b053..6e5e743cc 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -1436,6 +1436,7 @@ void Preprocessor::simplifyCondition(const std::map &c bool modified = true; while (modified) { modified = false; + modified |= tokenizer.simplifySizeof(); modified |= tokenizer.simplifyCalculations(); modified |= tokenizer.simplifyRedundantParenthesis(); for (Token *tok = const_cast(tokenizer.tokens()); tok; tok = tok->next()) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 47f69b590..7bff5ffcf 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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(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(size)); tok->deleteNext(3); + ret = true; } } @@ -3240,10 +3248,11 @@ void Tokenizer::simplifySizeof() if (sz > 0) { tok->str(MathLib::toString(sz)); Token::eraseTokens(tok, tok->next()->link()->next()); + ret = true; } } } - + return ret; } bool Tokenizer::simplifyTokenList() diff --git a/lib/tokenize.h b/lib/tokenize.h index 7ae819236..5a1e7cbdf 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -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) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index c5f35b1f7..e1d53a5e4 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -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 actual; + preprocessor.preprocess(istr, actual, "file.c"); + + ASSERT_EQUALS("\nFred & Wilma\n\n\n\n\n", actual[""]); + } }; REGISTER_TEST(TestPreprocessor)