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;
|
||||
ret.push_back("");
|
||||
|
||||
std::list<std::string> deflist;
|
||||
std::list<std::string> deflist, ndeflist;
|
||||
|
||||
// constants defined through "#define" in the code..
|
||||
std::set<std::string> defines;
|
||||
|
@ -679,7 +679,17 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|||
if (includeguard)
|
||||
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())
|
||||
{
|
||||
int par = 0;
|
||||
|
@ -736,7 +746,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|||
{
|
||||
if (*it == "0")
|
||||
break;
|
||||
if (*it == "1")
|
||||
if (*it == "1" || *it == "!")
|
||||
continue;
|
||||
|
||||
// don't add "T;T":
|
||||
|
@ -748,20 +758,43 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|||
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())
|
||||
{
|
||||
ret.push_back(def);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
deflist.pop_back();
|
||||
deflist.push_back(def);
|
||||
}
|
||||
}
|
||||
|
||||
else if (line.find("#endif") == 0 && ! deflist.empty())
|
||||
{
|
||||
if (deflist.back() == "!")
|
||||
ndeflist.pop_back();
|
||||
deflist.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove defined constants from ifdef configurations..
|
||||
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("\na\n\n\n\n\n", actual["A"]);
|
||||
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()
|
||||
|
|
Loading…
Reference in New Issue