Fixed #3536 (Preprocessor #if fails to correctly compare two #defined values)

This commit is contained in:
Daniel Marjamäki 2012-03-15 20:04:34 +01:00
parent 813a193bb6
commit fc84f55f80
3 changed files with 41 additions and 2 deletions

View File

@ -876,7 +876,25 @@ std::string Preprocessor::getdef(std::string line, bool def)
return line;
}
/**
* Simplifies the variable map. For example if the map contains A=>B, B=>1, then A=>B is simplified to A=>1.
* @param [in,out] variables - a map of variable name to variable value. This map will be modified.
*/
static void simplifyVarMap(std::map<std::string, std::string> &variables)
{
for (std::map<std::string, std::string>::iterator i = variables.begin(); i != variables.end(); ++i) {
std::string& varValue = i->second;
// TODO: 1. tokenize the value, replace each token like this.
// TODO: 2. handle function-macros too.
std::map<std::string, std::string>::iterator it = variables.find(varValue);
while (it != variables.end() && it != i) {
varValue = it->second;
it = variables.find(varValue);
}
}
}
std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const std::string &filename)
{
@ -998,6 +1016,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
varmap[varname] = value;
}
simplifyVarMap(varmap);
simplifyCondition(varmap, def, false);
}
@ -1386,7 +1405,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &c
condition = "0";
}
bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def)
bool Preprocessor::match_cfg_def(std::map<std::string, std::string> cfg, std::string def)
{
/*
std::cout << "cfg: \"";
@ -1401,6 +1420,7 @@ bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg,
std::cout << "def: \"" << def << "\"\n";
*/
simplifyVarMap(cfg);
simplifyCondition(cfg, def, true);
if (cfg.find(def) != cfg.end())

View File

@ -206,7 +206,7 @@ public:
* @param def condition
* @return result when evaluating the condition
*/
bool match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def);
bool match_cfg_def(std::map<std::string, std::string> cfg, std::string def);
static void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings);

View File

@ -128,6 +128,8 @@ private:
TEST_CASE(if_or_1);
TEST_CASE(if_or_2);
TEST_CASE(if_macro_eq_macro); // #3536
TEST_CASE(multiline1);
TEST_CASE(multiline2);
TEST_CASE(multiline3);
@ -1501,6 +1503,23 @@ private:
ASSERT_EQUALS("\na1;\n\n", preprocessor.getcode(code, "Y", "test.c"));
}
void if_macro_eq_macro() {
const std::string code("#define A B\n"
"#define B 1\n"
"#define C 1\n"
"#if A == C\n"
"Wilma\n"
"#else\n"
"Betty\n"
"#endif\n");
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("\n\n\n\nWilma\n\n\n\n", actual[""]);
}
void multiline1() {
const char filedata[] = "#define str \"abc\" \\\n"