Preprocessor: fix handling of (1&&2) condition

This commit is contained in:
Daniel Marjamäki 2011-07-16 09:24:27 +02:00
parent 274fd2b985
commit 07a1222ac6
3 changed files with 69 additions and 12 deletions

View File

@ -1446,7 +1446,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
} }
void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &variables, std::string &condition, bool match) void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &cfg, std::string &condition, bool match)
{ {
Settings settings; Settings settings;
Tokenizer tokenizer(&settings, NULL); Tokenizer tokenizer(&settings, NULL);
@ -1455,8 +1455,8 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
if (Token::Match(tokenizer.tokens(), "( %var% )")) if (Token::Match(tokenizer.tokens(), "( %var% )"))
{ {
std::map<std::string,std::string>::const_iterator var = variables.find(tokenizer.tokens()->strAt(1)); std::map<std::string,std::string>::const_iterator var = cfg.find(tokenizer.tokens()->strAt(1));
if (var != variables.end()) if (var != cfg.end())
{ {
const std::string &value = (*var).second; const std::string &value = (*var).second;
condition = (value == "0") ? "0" : "1"; condition = (value == "0") ? "0" : "1";
@ -1468,7 +1468,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
if (Token::Match(tokenizer.tokens(), "( ! %var% )")) if (Token::Match(tokenizer.tokens(), "( ! %var% )"))
{ {
if (variables.find(tokenizer.tokens()->strAt(2)) == variables.end()) if (cfg.find(tokenizer.tokens()->strAt(2)) == cfg.end())
condition = "1"; condition = "1";
else if (match) else if (match)
condition = "0"; condition = "0";
@ -1483,7 +1483,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
if (Token::Match(tok, "defined ( %var% )")) if (Token::Match(tok, "defined ( %var% )"))
{ {
if (variables.find(tok->strAt(2)) != variables.end()) if (cfg.find(tok->strAt(2)) != cfg.end())
tok->str("1"); tok->str("1");
else if (match) else if (match)
tok->str("0"); tok->str("0");
@ -1497,7 +1497,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
if (Token::Match(tok, "defined %var%")) if (Token::Match(tok, "defined %var%"))
{ {
if (variables.find(tok->strAt(1)) != variables.end()) if (cfg.find(tok->strAt(1)) != cfg.end())
tok->str("1"); tok->str("1");
else if (match) else if (match)
tok->str("0"); tok->str("0");
@ -1507,8 +1507,8 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
continue; continue;
} }
const std::map<std::string, std::string>::const_iterator it = variables.find(tok->str()); const std::map<std::string, std::string>::const_iterator it = cfg.find(tok->str());
if (it != variables.end()) if (it != cfg.end())
{ {
if (!it->second.empty()) if (!it->second.empty())
{ {
@ -1563,6 +1563,17 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
} }
} }
for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next())
{
if (Token::Match(tok, "(|%oror%|&& %num% &&|%oror%|)"))
{
if (tok->next()->str() != "0")
{
tok->next()->str("1");
}
}
}
for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next()) for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next())
{ {
while (Token::Match(tok, "(|%oror% %any% %oror% 1")) while (Token::Match(tok, "(|%oror% %any% %oror% 1"))
@ -1583,8 +1594,18 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def) bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def)
{ {
//std::cout << "cfg: \"" << cfg << "\" "; /*
//std::cout << "def: \"" << def << "\""; std::cout << "cfg: \"";
for (std::map<std::string, std::string>::const_iterator it = cfg.begin(); it != cfg.end(); ++it)
{
std::cout << it->first;
if (!it->second.empty())
std::cout << "=" << it->second;
std::cout << ";";
}
std::cout << "\" ";
std::cout << "def: \"" << def << "\"\n";
*/
simplifyCondition(cfg, def, true); simplifyCondition(cfg, def, true);
@ -1601,7 +1622,7 @@ bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg,
} }
std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, const std::string &filename, const Settings *settings, ErrorLogger *errorLogger) std::string Preprocessor::getcode(const std::string &filedata, const std::string &cfg, const std::string &filename, const Settings *settings, ErrorLogger *errorLogger)
{ {
// For the error report // For the error report
unsigned int lineno = 0; unsigned int lineno = 0;

View File

@ -93,7 +93,7 @@ public:
/** /**
* Get preprocessed code for a given configuration * Get preprocessed code for a given configuration
*/ */
static std::string getcode(const std::string &filedata, std::string cfg, const std::string &filename, const Settings *settings, ErrorLogger *errorLogger); static std::string getcode(const std::string &filedata, const std::string &cfg, const std::string &filename, const Settings *settings, ErrorLogger *errorLogger);
/** /**
* simplify condition * simplify condition

View File

@ -221,6 +221,10 @@ private:
// inline suppression, missingInclude // inline suppression, missingInclude
TEST_CASE(inline_suppression_for_missing_include); TEST_CASE(inline_suppression_for_missing_include);
// Using -D to predefine symbols
TEST_CASE(predefine1);
TEST_CASE(predefine2);
} }
@ -2853,6 +2857,38 @@ private:
preprocessor.preprocess(src, processedFile, cfg, "test.c", paths); preprocessor.preprocess(src, processedFile, cfg, "test.c", paths);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void predefine1()
{
Settings settings;
const std::string src("#ifdef X || Y\n"
"Fred & Wilma\n"
"#endif\n");
std::string actual = Preprocessor::getcode(src, "X=1", "test.c", &settings, this);
ASSERT_EQUALS("\nFred & Wilma\n\n", actual);
}
void predefine2()
{
Settings settings;
const std::string src("#ifdef X && Y\n"
"Fred & Wilma\n"
"#endif\n");
{
std::string actual = Preprocessor::getcode(src, "X=1", "test.c", &settings, this);
ASSERT_EQUALS("\n\n\n", actual);
}
{
std::string actual = Preprocessor::getcode(src, "X=1;Y=2", "test.c", &settings, this);
ASSERT_EQUALS("\nFred & Wilma\n\n", actual);
}
}
}; };
REGISTER_TEST(TestPreprocessor) REGISTER_TEST(TestPreprocessor)