Fixed #3536 (Preprocessor #if fails to correctly compare two #defined values)
This commit is contained in:
parent
813a193bb6
commit
fc84f55f80
|
@ -876,7 +876,25 @@ std::string Preprocessor::getdef(std::string line, bool def)
|
||||||
return line;
|
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)
|
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;
|
varmap[varname] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simplifyVarMap(varmap);
|
||||||
simplifyCondition(varmap, def, false);
|
simplifyCondition(varmap, def, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,7 +1405,7 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &c
|
||||||
condition = "0";
|
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: \"";
|
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";
|
std::cout << "def: \"" << def << "\"\n";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
simplifyVarMap(cfg);
|
||||||
simplifyCondition(cfg, def, true);
|
simplifyCondition(cfg, def, true);
|
||||||
|
|
||||||
if (cfg.find(def) != cfg.end())
|
if (cfg.find(def) != cfg.end())
|
||||||
|
|
|
@ -206,7 +206,7 @@ public:
|
||||||
* @param def condition
|
* @param def condition
|
||||||
* @return result when evaluating the 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);
|
static void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings);
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,8 @@ private:
|
||||||
TEST_CASE(if_or_1);
|
TEST_CASE(if_or_1);
|
||||||
TEST_CASE(if_or_2);
|
TEST_CASE(if_or_2);
|
||||||
|
|
||||||
|
TEST_CASE(if_macro_eq_macro); // #3536
|
||||||
|
|
||||||
TEST_CASE(multiline1);
|
TEST_CASE(multiline1);
|
||||||
TEST_CASE(multiline2);
|
TEST_CASE(multiline2);
|
||||||
TEST_CASE(multiline3);
|
TEST_CASE(multiline3);
|
||||||
|
@ -1501,6 +1503,23 @@ private:
|
||||||
ASSERT_EQUALS("\na1;\n\n", preprocessor.getcode(code, "Y", "test.c"));
|
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() {
|
void multiline1() {
|
||||||
const char filedata[] = "#define str \"abc\" \\\n"
|
const char filedata[] = "#define str \"abc\" \\\n"
|
||||||
|
|
Loading…
Reference in New Issue