Fixed #1512 (incorrect handling of ndefs in the preprocessor)

This commit is contained in:
Raphael Geissert 2010-03-19 16:13:45 +01:00 committed by Daniel Marjamäki
parent c7bd437d7d
commit d11004fa3d
2 changed files with 124 additions and 6 deletions

View File

@ -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)

View File

@ -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()