Fixed #1512 (incorrect handling of ndefs in the preprocessor)
This commit is contained in:
parent
c7bd437d7d
commit
d11004fa3d
|
@ -628,7 +628,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
std::list<std::string> ret;
|
std::list<std::string> ret;
|
||||||
ret.push_back("");
|
ret.push_back("");
|
||||||
|
|
||||||
std::list<std::string> deflist;
|
std::list<std::string> deflist, ndeflist;
|
||||||
|
|
||||||
// constants defined through "#define" in the code..
|
// constants defined through "#define" in the code..
|
||||||
std::set<std::string> defines;
|
std::set<std::string> defines;
|
||||||
|
@ -679,7 +679,17 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
if (includeguard)
|
if (includeguard)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string def = getdef(line, true) + getdef(line, false);
|
bool from_negation = false;
|
||||||
|
|
||||||
|
std::string def = getdef(line, true);
|
||||||
|
if (def.empty())
|
||||||
|
{
|
||||||
|
def = getdef(line, false);
|
||||||
|
// sub conditionals of ndef blocks need to be
|
||||||
|
// constructed _without_ the negated define
|
||||||
|
if (!def.empty())
|
||||||
|
from_negation = true;
|
||||||
|
}
|
||||||
if (!def.empty())
|
if (!def.empty())
|
||||||
{
|
{
|
||||||
int par = 0;
|
int par = 0;
|
||||||
|
@ -736,7 +746,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
{
|
{
|
||||||
if (*it == "0")
|
if (*it == "0")
|
||||||
break;
|
break;
|
||||||
if (*it == "1")
|
if (*it == "1" || *it == "!")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// don't add "T;T":
|
// don't add "T;T":
|
||||||
|
@ -748,20 +758,43 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
def += *it;
|
def += *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (from_negation)
|
||||||
|
{
|
||||||
|
ndeflist.push_back(deflist.back());
|
||||||
|
deflist.pop_back();
|
||||||
|
std::string nmark("!");
|
||||||
|
deflist.push_back(nmark);
|
||||||
|
}
|
||||||
|
|
||||||
if (std::find(ret.begin(), ret.end(), def) == ret.end())
|
if (std::find(ret.begin(), ret.end(), def) == ret.end())
|
||||||
|
{
|
||||||
ret.push_back(def);
|
ret.push_back(def);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if (line.find("#else") == 0 && ! deflist.empty())
|
else if (line.find("#else") == 0 && ! deflist.empty())
|
||||||
|
{
|
||||||
|
if (deflist.back() == "!")
|
||||||
|
{
|
||||||
|
deflist.pop_back();
|
||||||
|
deflist.push_back(ndeflist.back());
|
||||||
|
ndeflist.pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
std::string def((deflist.back() == "1") ? "0" : "1");
|
std::string def((deflist.back() == "1") ? "0" : "1");
|
||||||
deflist.pop_back();
|
deflist.pop_back();
|
||||||
deflist.push_back(def);
|
deflist.push_back(def);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if (line.find("#endif") == 0 && ! deflist.empty())
|
else if (line.find("#endif") == 0 && ! deflist.empty())
|
||||||
|
{
|
||||||
|
if (deflist.back() == "!")
|
||||||
|
ndeflist.pop_back();
|
||||||
deflist.pop_back();
|
deflist.pop_back();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove defined constants from ifdef configurations..
|
// Remove defined constants from ifdef configurations..
|
||||||
for (std::list<std::string>::iterator it = ret.begin(); it != ret.end(); ++it)
|
for (std::list<std::string>::iterator it = ret.begin(); it != ret.end(); ++it)
|
||||||
|
|
|
@ -716,6 +716,91 @@ private:
|
||||||
ASSERT_EQUALS("\n\n\n\n\n\n", actual[""]);
|
ASSERT_EQUALS("\n\n\n\n\n\n", actual[""]);
|
||||||
ASSERT_EQUALS("\na\n\n\n\n\n", actual["A"]);
|
ASSERT_EQUALS("\na\n\n\n\n\n", actual["A"]);
|
||||||
ASSERT_EQUALS("\na\n\n\nab\n\n", actual["A;B"]);
|
ASSERT_EQUALS("\na\n\n\nab\n\n", actual["A;B"]);
|
||||||
|
if_cond2b();
|
||||||
|
if_cond2c();
|
||||||
|
if_cond2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_cond2b()
|
||||||
|
{
|
||||||
|
const char filedata[] = "#ifndef A\n"
|
||||||
|
"!a\n"
|
||||||
|
"#ifdef B\n"
|
||||||
|
"b\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#else\n"
|
||||||
|
"a\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
Preprocessor preprocessor;
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(3, static_cast<unsigned int>(actual.size()));
|
||||||
|
ASSERT_EQUALS("\n!a\n\n\n\n\n\n\n", actual[""]);
|
||||||
|
ASSERT_EQUALS("\n\n\n\n\n\na\n\n", actual["A"]);
|
||||||
|
ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n", actual["B"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_cond2c()
|
||||||
|
{
|
||||||
|
const char filedata[] = "#ifndef A\n"
|
||||||
|
"!a\n"
|
||||||
|
"#ifdef B\n"
|
||||||
|
"b\n"
|
||||||
|
"#else\n"
|
||||||
|
"!b\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#else\n"
|
||||||
|
"a\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
Preprocessor preprocessor;
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(3, static_cast<unsigned int>(actual.size()));
|
||||||
|
ASSERT_EQUALS("\n!a\n\n\n\n!b\n\n\n\n\n", actual[""]);
|
||||||
|
ASSERT_EQUALS("\n\n\n\n\n\n\n\na\n\n", actual["A"]);
|
||||||
|
ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n\n\n", actual["B"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_cond2d()
|
||||||
|
{
|
||||||
|
const char filedata[] = "#ifndef A\n"
|
||||||
|
"!a\n"
|
||||||
|
"#ifdef B\n"
|
||||||
|
"b\n"
|
||||||
|
"#else\n"
|
||||||
|
"!b\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#else\n"
|
||||||
|
"a\n"
|
||||||
|
"#ifdef B\n"
|
||||||
|
"b\n"
|
||||||
|
"#else\n"
|
||||||
|
"!b\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
Preprocessor preprocessor;
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(4, static_cast<unsigned int>(actual.size()));
|
||||||
|
ASSERT_EQUALS("\n!a\n\n\n\n!b\n\n\n\n\n\n\n\n\n\n", actual[""]);
|
||||||
|
ASSERT_EQUALS("\n\n\n\n\n\n\n\na\n\n\n\n!b\n\n\n", actual["A"]);
|
||||||
|
ASSERT_EQUALS("\n\n\n\n\n\n\n\na\n\nb\n\n\n\n\n", actual["A;B"]);
|
||||||
|
ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n\n\n\n\n\n\n\n", actual["B"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void if_cond3()
|
void if_cond3()
|
||||||
|
|
Loading…
Reference in New Issue